@microphi/json-db 2.2.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +52 -3
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -2
- package/lib/lib/storage/json-storage.d.ts +43 -0
- package/lib/lib/storage/json-storage.d.ts.map +1 -0
- package/lib/lib/storage/json-storage.js +200 -0
- package/package.json +14 -4
- package/lib/index.js.map +0 -1
- package/lib/lib/aspects/after.decorator.d.ts +0 -35
- package/lib/lib/aspects/after.decorator.d.ts.map +0 -1
- package/lib/lib/aspects/after.decorator.js +0 -45
- package/lib/lib/aspects/after.decorator.js.map +0 -1
- package/lib/lib/aspects/before.decorator.d.ts +0 -28
- package/lib/lib/aspects/before.decorator.d.ts.map +0 -1
- package/lib/lib/aspects/before.decorator.js +0 -46
- package/lib/lib/aspects/before.decorator.js.map +0 -1
- package/lib/lib/container/bootstrap.d.ts +0 -3
- package/lib/lib/container/bootstrap.d.ts.map +0 -1
- package/lib/lib/container/bootstrap.js +0 -15
- package/lib/lib/container/bootstrap.js.map +0 -1
- package/lib/lib/container/di.decorator.d.ts +0 -10
- package/lib/lib/container/di.decorator.d.ts.map +0 -1
- package/lib/lib/container/di.decorator.js +0 -15
- package/lib/lib/container/di.decorator.js.map +0 -1
- package/lib/lib/container/graph.d.ts +0 -171
- package/lib/lib/container/graph.d.ts.map +0 -1
- package/lib/lib/container/graph.js +0 -429
- package/lib/lib/container/graph.js.map +0 -1
- package/lib/lib/injctable/inject.decorator.d.ts +0 -7
- package/lib/lib/injctable/inject.decorator.d.ts.map +0 -1
- package/lib/lib/injctable/inject.decorator.js +0 -31
- package/lib/lib/injctable/inject.decorator.js.map +0 -1
- package/lib/lib/injctable/injectable.decorator.d.ts +0 -16
- package/lib/lib/injctable/injectable.decorator.d.ts.map +0 -1
- package/lib/lib/injctable/injectable.decorator.js +0 -52
- package/lib/lib/injctable/injectable.decorator.js.map +0 -1
- package/lib/lib/injctable/injector.d.ts +0 -4
- package/lib/lib/injctable/injector.d.ts.map +0 -1
- package/lib/lib/injctable/injector.js +0 -25
- package/lib/lib/injctable/injector.js.map +0 -1
- package/lib/lib/list/list.d.ts +0 -28
- package/lib/lib/list/list.d.ts.map +0 -1
- package/lib/lib/list/list.js +0 -94
- package/lib/lib/list/list.js.map +0 -1
- package/lib/lib/provider/providers.d.ts +0 -15
- package/lib/lib/provider/providers.d.ts.map +0 -1
- package/lib/lib/provider/providers.js +0 -80
- package/lib/lib/provider/providers.js.map +0 -1
- package/lib/lib/scan.d.ts +0 -3
- package/lib/lib/scan.d.ts.map +0 -1
- package/lib/lib/scan.js +0 -19
- package/lib/lib/scan.js.map +0 -1
- package/lib/lib/testing/mocked.d.ts +0 -9
- package/lib/lib/testing/mocked.d.ts.map +0 -1
- package/lib/lib/testing/mocked.js +0 -58
- package/lib/lib/testing/mocked.js.map +0 -1
- package/lib/lib/testing/test-bed.d.ts +0 -7
- package/lib/lib/testing/test-bed.d.ts.map +0 -1
- package/lib/lib/testing/test-bed.js +0 -20
- package/lib/lib/testing/test-bed.js.map +0 -1
- package/lib/lib/types.d.ts +0 -10
- package/lib/lib/types.d.ts.map +0 -1
- package/lib/lib/types.js +0 -4
- package/lib/lib/types.js.map +0 -1
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
export type NodeId = string;
|
|
2
|
-
export type EdgeWeight = number;
|
|
3
|
-
export type EncodedEdge = string;
|
|
4
|
-
export interface Serialized {
|
|
5
|
-
nodes: {
|
|
6
|
-
id: NodeId;
|
|
7
|
-
}[];
|
|
8
|
-
links: {
|
|
9
|
-
source: NodeId;
|
|
10
|
-
target: NodeId;
|
|
11
|
-
weight: EdgeWeight;
|
|
12
|
-
}[];
|
|
13
|
-
}
|
|
14
|
-
export declare class CycleError extends Error {
|
|
15
|
-
constructor(message: string);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* A graph data structure with depth-first search and topological sort.
|
|
19
|
-
*/
|
|
20
|
-
export declare class Graph {
|
|
21
|
-
/**
|
|
22
|
-
* The adjacency list of the graph.
|
|
23
|
-
* Keys are node ids.
|
|
24
|
-
* Values are adjacent node id arrays.
|
|
25
|
-
*/
|
|
26
|
-
edges: Record<NodeId, NodeId[]>;
|
|
27
|
-
/**
|
|
28
|
-
* The weights of edges.
|
|
29
|
-
* Keys are string encodings of edges.
|
|
30
|
-
* Values are weights (numbers).
|
|
31
|
-
*/
|
|
32
|
-
edgeWeights: Record<EncodedEdge, EdgeWeight>;
|
|
33
|
-
constructor(serialized?: Serialized);
|
|
34
|
-
/**
|
|
35
|
-
* Deserializes the given serialized graph.
|
|
36
|
-
* @param serialized
|
|
37
|
-
*/
|
|
38
|
-
deserialize(serialized: Serialized): this;
|
|
39
|
-
/**
|
|
40
|
-
* Gets the adjacent node list for the given node.
|
|
41
|
-
* Returns an empty array for unknown nodes.
|
|
42
|
-
* @param node
|
|
43
|
-
*/
|
|
44
|
-
adjacent(node: NodeId): NodeId[];
|
|
45
|
-
/**
|
|
46
|
-
* Adds a node to the graph.
|
|
47
|
-
* If node was already added, this function does nothing.
|
|
48
|
-
* If node was not already added, this function sets up an empty adjacency list.
|
|
49
|
-
* @param node
|
|
50
|
-
*/
|
|
51
|
-
addNode(node: NodeId): this;
|
|
52
|
-
/**
|
|
53
|
-
* Adds an edge from node u to node v.
|
|
54
|
-
* Implicitly adds the nodes if they were not already added.
|
|
55
|
-
* @param u
|
|
56
|
-
* @param v
|
|
57
|
-
* @param weight
|
|
58
|
-
*/
|
|
59
|
-
addEdge(u: NodeId, v: NodeId, weight?: EdgeWeight): this;
|
|
60
|
-
/**
|
|
61
|
-
* Sets the weight of the given edge.
|
|
62
|
-
* @param u
|
|
63
|
-
* @param v
|
|
64
|
-
* @param weight
|
|
65
|
-
*/
|
|
66
|
-
setEdgeWeight(u: NodeId, v: NodeId, weight: EdgeWeight): this;
|
|
67
|
-
/**
|
|
68
|
-
* Computes a string encoding of an edge,
|
|
69
|
-
* for use as a key in an object.
|
|
70
|
-
* @param u
|
|
71
|
-
* @param v
|
|
72
|
-
*/
|
|
73
|
-
encodeEdge(u: NodeId, v: NodeId): EncodedEdge;
|
|
74
|
-
/**
|
|
75
|
-
* Removes a node from the graph.
|
|
76
|
-
* Also removes incoming and outgoing edges.
|
|
77
|
-
* @param node
|
|
78
|
-
*/
|
|
79
|
-
removeNode(node: NodeId): this;
|
|
80
|
-
/**
|
|
81
|
-
* Gets the list of nodes that have been added to the graph.
|
|
82
|
-
*/
|
|
83
|
-
nodes(): NodeId[];
|
|
84
|
-
/**
|
|
85
|
-
* Gets the weight of the given edge.
|
|
86
|
-
* Returns 1 if no weight was previously set.
|
|
87
|
-
* @param u
|
|
88
|
-
* @param v
|
|
89
|
-
*/
|
|
90
|
-
getEdgeWeight(u: NodeId, v: NodeId): EdgeWeight;
|
|
91
|
-
/**
|
|
92
|
-
* Removes the edge from node u to node v.
|
|
93
|
-
* Does not remove the nodes.
|
|
94
|
-
* Does nothing if the edge does not exist.
|
|
95
|
-
* @param u
|
|
96
|
-
* @param v
|
|
97
|
-
*/
|
|
98
|
-
removeEdge(u: NodeId, v: NodeId): this;
|
|
99
|
-
/**
|
|
100
|
-
* Returns true if there is an edge from node u to node v.
|
|
101
|
-
* @param u
|
|
102
|
-
* @param v
|
|
103
|
-
*/
|
|
104
|
-
hasEdge(u: NodeId, v: NodeId): boolean;
|
|
105
|
-
/**
|
|
106
|
-
* Computes the indegree for the given node.
|
|
107
|
-
* Not very efficient, costs O(E) where E = number of edges.
|
|
108
|
-
*
|
|
109
|
-
* @param node
|
|
110
|
-
*/
|
|
111
|
-
inDegree(node: NodeId): number;
|
|
112
|
-
/**
|
|
113
|
-
* Computes the outdegree for the given node.
|
|
114
|
-
*
|
|
115
|
-
* @param node
|
|
116
|
-
*/
|
|
117
|
-
outDegree(node: NodeId): number;
|
|
118
|
-
/**
|
|
119
|
-
* Depth First Search algorithm, inspired by
|
|
120
|
-
* Cormen et al. 'Introduction to Algorithms' 3rd Ed. p. 604
|
|
121
|
-
* The additional option `includeSourceNodes` specifies whether to
|
|
122
|
-
* include or exclude the source nodes from the result (true by default).
|
|
123
|
-
* If `sourceNodes` is not specified, all nodes in the graph
|
|
124
|
-
* are used as source nodes.
|
|
125
|
-
*
|
|
126
|
-
* @param sourceNodes
|
|
127
|
-
* @param includeSourceNodes
|
|
128
|
-
* @param errorOnCycle
|
|
129
|
-
*/
|
|
130
|
-
depthFirstSearch(sourceNodes: NodeId[] | undefined, includeSourceNodes?: boolean, errorOnCycle?: boolean): string[];
|
|
131
|
-
/**
|
|
132
|
-
* Returns true if the graph has one or more cycles and false otherwise
|
|
133
|
-
*/
|
|
134
|
-
hasCycle(): boolean;
|
|
135
|
-
/**
|
|
136
|
-
* Least Common Ancestors
|
|
137
|
-
* Inspired by https://github.com/relaxedws/lca/blob/master/src/LowestCommonAncestor.php code
|
|
138
|
-
* but uses depth search instead of breadth. Also uses some optimizations
|
|
139
|
-
*
|
|
140
|
-
* @param node1
|
|
141
|
-
* @param node2
|
|
142
|
-
*/
|
|
143
|
-
lowestCommonAncestors(node1: NodeId, node2: NodeId): string[];
|
|
144
|
-
/**
|
|
145
|
-
* The topological sort algorithm yields a list of visited nodes
|
|
146
|
-
* such that for each visited edge (u, v), u comes before v in the list.
|
|
147
|
-
* Amazingly, this comes from just reversing the result from depth first search.
|
|
148
|
-
* Cormen et al. 'Introduction to Algorithms' 3rd Ed. p. 613
|
|
149
|
-
*
|
|
150
|
-
* @param sourceNodes
|
|
151
|
-
* @param includeSourceNodes
|
|
152
|
-
*/
|
|
153
|
-
topologicalSort(sourceNodes?: NodeId[], includeSourceNodes?: boolean): string[];
|
|
154
|
-
/**
|
|
155
|
-
* Dijkstra's Shortest Path Algorithm.
|
|
156
|
-
* Cormen et al. 'Introduction to Algorithms' 3rd Ed. p. 658
|
|
157
|
-
* Variable and function names correspond to names in the book.
|
|
158
|
-
*
|
|
159
|
-
* @param source
|
|
160
|
-
* @param destination
|
|
161
|
-
*/
|
|
162
|
-
shortestPath(source: NodeId, destination: NodeId): {
|
|
163
|
-
path: NodeId[];
|
|
164
|
-
weight: EdgeWeight;
|
|
165
|
-
};
|
|
166
|
-
/**
|
|
167
|
-
* Serializes the graph.
|
|
168
|
-
*/
|
|
169
|
-
serialize(): Serialized;
|
|
170
|
-
}
|
|
171
|
-
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/lib/container/graph.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAC5B,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC;AAChC,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;CACjE;AAED,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,KAAK;IAChB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAM;IAErC;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,CAAM;gBAEtC,UAAU,CAAC,EAAE,UAAU;IAMnC;;;OAGG;IACH,WAAW,CAAC,UAAU,EAAE,UAAU;IAUlC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAIhC;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM;IAKpB;;;;;;OAMG;IACH,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU;IAYjD;;;;;OAKG;IACH,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU;IAKtD;;;;;OAKG;IACH,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW;IAI7C;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM;IAgBvB;;OAEG;IACH,KAAK,IAAI,MAAM,EAAE;IAajB;;;;;OAKG;IACH,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU;IAK/C;;;;;;OAMG;IACH,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;IAS/B;;;;OAIG;IACH,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;IAI5B;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM;IAarB;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM;IAKtB;;;;;;;;;;;OAWG;IACH,gBAAgB,CACd,WAAW,EAAE,MAAM,EAAE,GAAC,SAAS,EAC/B,kBAAkB,GAAE,OAAc,EAClC,YAAY,GAAE,OAAe;IA0C/B;;OAEG;IACH,QAAQ,IAAI,OAAO;IAgBnB;;;;;;;OAOG;IACH,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IA4ClD;;;;;;;;OAQG;IACH,eAAe,CACb,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,kBAAkB,GAAE,OAAc;IAKpC;;;;;;;OAOG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;cA6EpB,MAAM,EAAE;gBAAU,UAAU;;IAwBxD;;OAEG;IACH,SAAS;CAqBV"}
|
|
@@ -1,429 +0,0 @@
|
|
|
1
|
-
export class CycleError extends Error {
|
|
2
|
-
constructor(message) {
|
|
3
|
-
super(message);
|
|
4
|
-
Object.setPrototypeOf(this, CycleError.prototype);
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* A graph data structure with depth-first search and topological sort.
|
|
9
|
-
*/
|
|
10
|
-
export class Graph {
|
|
11
|
-
constructor(serialized) {
|
|
12
|
-
/**
|
|
13
|
-
* The adjacency list of the graph.
|
|
14
|
-
* Keys are node ids.
|
|
15
|
-
* Values are adjacent node id arrays.
|
|
16
|
-
*/
|
|
17
|
-
this.edges = {};
|
|
18
|
-
/**
|
|
19
|
-
* The weights of edges.
|
|
20
|
-
* Keys are string encodings of edges.
|
|
21
|
-
* Values are weights (numbers).
|
|
22
|
-
*/
|
|
23
|
-
this.edgeWeights = {};
|
|
24
|
-
if (serialized) {
|
|
25
|
-
this.deserialize(serialized);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Deserializes the given serialized graph.
|
|
30
|
-
* @param serialized
|
|
31
|
-
*/
|
|
32
|
-
deserialize(serialized) {
|
|
33
|
-
serialized.nodes.forEach((node) => {
|
|
34
|
-
this.addNode(node.id);
|
|
35
|
-
});
|
|
36
|
-
serialized.links.forEach((link) => {
|
|
37
|
-
this.addEdge(link.source, link.target, link.weight);
|
|
38
|
-
});
|
|
39
|
-
return this;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Gets the adjacent node list for the given node.
|
|
43
|
-
* Returns an empty array for unknown nodes.
|
|
44
|
-
* @param node
|
|
45
|
-
*/
|
|
46
|
-
adjacent(node) {
|
|
47
|
-
return this.edges[node] || [];
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Adds a node to the graph.
|
|
51
|
-
* If node was already added, this function does nothing.
|
|
52
|
-
* If node was not already added, this function sets up an empty adjacency list.
|
|
53
|
-
* @param node
|
|
54
|
-
*/
|
|
55
|
-
addNode(node) {
|
|
56
|
-
this.edges[node] = this.adjacent(node);
|
|
57
|
-
return this;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Adds an edge from node u to node v.
|
|
61
|
-
* Implicitly adds the nodes if they were not already added.
|
|
62
|
-
* @param u
|
|
63
|
-
* @param v
|
|
64
|
-
* @param weight
|
|
65
|
-
*/
|
|
66
|
-
addEdge(u, v, weight) {
|
|
67
|
-
this.addNode(u);
|
|
68
|
-
this.addNode(v);
|
|
69
|
-
this.adjacent(u).push(v);
|
|
70
|
-
if (weight !== undefined) {
|
|
71
|
-
this.setEdgeWeight(u, v, weight);
|
|
72
|
-
}
|
|
73
|
-
return this;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Sets the weight of the given edge.
|
|
77
|
-
* @param u
|
|
78
|
-
* @param v
|
|
79
|
-
* @param weight
|
|
80
|
-
*/
|
|
81
|
-
setEdgeWeight(u, v, weight) {
|
|
82
|
-
this.edgeWeights[this.encodeEdge(u, v)] = weight;
|
|
83
|
-
return this;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Computes a string encoding of an edge,
|
|
87
|
-
* for use as a key in an object.
|
|
88
|
-
* @param u
|
|
89
|
-
* @param v
|
|
90
|
-
*/
|
|
91
|
-
encodeEdge(u, v) {
|
|
92
|
-
return u + '|' + v;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Removes a node from the graph.
|
|
96
|
-
* Also removes incoming and outgoing edges.
|
|
97
|
-
* @param node
|
|
98
|
-
*/
|
|
99
|
-
removeNode(node) {
|
|
100
|
-
// Remove incoming edges.
|
|
101
|
-
Object.keys(this.edges).forEach((u) => {
|
|
102
|
-
this.edges[u].forEach((v) => {
|
|
103
|
-
if (v === node) {
|
|
104
|
-
this.removeEdge(u, v);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
// Remove outgoing edges (and signal that the node no longer exists).
|
|
109
|
-
delete this.edges[node];
|
|
110
|
-
return this;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Gets the list of nodes that have been added to the graph.
|
|
114
|
-
*/
|
|
115
|
-
nodes() {
|
|
116
|
-
// TODO: Better implementation with set data structure
|
|
117
|
-
const nodeSet = {};
|
|
118
|
-
Object.keys(this.edges).forEach((u) => {
|
|
119
|
-
nodeSet[u] = true;
|
|
120
|
-
this.edges[u].forEach((v) => {
|
|
121
|
-
nodeSet[v] = true;
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
return Object.keys(nodeSet);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Gets the weight of the given edge.
|
|
128
|
-
* Returns 1 if no weight was previously set.
|
|
129
|
-
* @param u
|
|
130
|
-
* @param v
|
|
131
|
-
*/
|
|
132
|
-
getEdgeWeight(u, v) {
|
|
133
|
-
const weight = this.edgeWeights[this.encodeEdge(u, v)];
|
|
134
|
-
return weight ?? 1;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Removes the edge from node u to node v.
|
|
138
|
-
* Does not remove the nodes.
|
|
139
|
-
* Does nothing if the edge does not exist.
|
|
140
|
-
* @param u
|
|
141
|
-
* @param v
|
|
142
|
-
*/
|
|
143
|
-
removeEdge(u, v) {
|
|
144
|
-
if (this.edges[u]) {
|
|
145
|
-
this.edges[u] = this.adjacent(u).filter((_v) => {
|
|
146
|
-
return _v !== v;
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
return this;
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Returns true if there is an edge from node u to node v.
|
|
153
|
-
* @param u
|
|
154
|
-
* @param v
|
|
155
|
-
*/
|
|
156
|
-
hasEdge(u, v) {
|
|
157
|
-
return this.adjacent(u).includes(v);
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Computes the indegree for the given node.
|
|
161
|
-
* Not very efficient, costs O(E) where E = number of edges.
|
|
162
|
-
*
|
|
163
|
-
* @param node
|
|
164
|
-
*/
|
|
165
|
-
inDegree(node) {
|
|
166
|
-
let degree = 0;
|
|
167
|
-
function check(v) {
|
|
168
|
-
if (v === node) {
|
|
169
|
-
degree++;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
Object.keys(this.edges).forEach((u) => {
|
|
173
|
-
this.edges[u].forEach(check);
|
|
174
|
-
});
|
|
175
|
-
return degree;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Computes the outdegree for the given node.
|
|
179
|
-
*
|
|
180
|
-
* @param node
|
|
181
|
-
*/
|
|
182
|
-
outDegree(node) {
|
|
183
|
-
return node in this.edges ? this.edges[node].length : 0;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Depth First Search algorithm, inspired by
|
|
187
|
-
* Cormen et al. 'Introduction to Algorithms' 3rd Ed. p. 604
|
|
188
|
-
* The additional option `includeSourceNodes` specifies whether to
|
|
189
|
-
* include or exclude the source nodes from the result (true by default).
|
|
190
|
-
* If `sourceNodes` is not specified, all nodes in the graph
|
|
191
|
-
* are used as source nodes.
|
|
192
|
-
*
|
|
193
|
-
* @param sourceNodes
|
|
194
|
-
* @param includeSourceNodes
|
|
195
|
-
* @param errorOnCycle
|
|
196
|
-
*/
|
|
197
|
-
depthFirstSearch(sourceNodes, includeSourceNodes = true, errorOnCycle = false) {
|
|
198
|
-
if (!sourceNodes) {
|
|
199
|
-
sourceNodes = this.nodes();
|
|
200
|
-
}
|
|
201
|
-
if (typeof includeSourceNodes !== 'boolean') {
|
|
202
|
-
includeSourceNodes = true;
|
|
203
|
-
}
|
|
204
|
-
const visited = {};
|
|
205
|
-
const visiting = {};
|
|
206
|
-
const nodeList = [];
|
|
207
|
-
const DFSVisit = (node) => {
|
|
208
|
-
if (visiting[node] && errorOnCycle) {
|
|
209
|
-
throw new CycleError('Cycle found');
|
|
210
|
-
}
|
|
211
|
-
if (!visited[node]) {
|
|
212
|
-
visited[node] = true;
|
|
213
|
-
visiting[node] = true; // temporary flag while visiting
|
|
214
|
-
this.adjacent(node).forEach(DFSVisit);
|
|
215
|
-
visiting[node] = false;
|
|
216
|
-
nodeList.push(node);
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
if (includeSourceNodes) {
|
|
220
|
-
sourceNodes.forEach(DFSVisit);
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
sourceNodes.forEach((node) => {
|
|
224
|
-
visited[node] = true;
|
|
225
|
-
});
|
|
226
|
-
sourceNodes.forEach((node) => {
|
|
227
|
-
this.adjacent(node).forEach(DFSVisit);
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
return nodeList;
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Returns true if the graph has one or more cycles and false otherwise
|
|
234
|
-
*/
|
|
235
|
-
hasCycle() {
|
|
236
|
-
try {
|
|
237
|
-
this.depthFirstSearch(undefined, true, true);
|
|
238
|
-
// No error thrown -> no cycles
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
catch (error) {
|
|
242
|
-
if (error instanceof CycleError) {
|
|
243
|
-
return true;
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
throw error;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Least Common Ancestors
|
|
252
|
-
* Inspired by https://github.com/relaxedws/lca/blob/master/src/LowestCommonAncestor.php code
|
|
253
|
-
* but uses depth search instead of breadth. Also uses some optimizations
|
|
254
|
-
*
|
|
255
|
-
* @param node1
|
|
256
|
-
* @param node2
|
|
257
|
-
*/
|
|
258
|
-
lowestCommonAncestors(node1, node2) {
|
|
259
|
-
const node1Ancestors = [];
|
|
260
|
-
const lcas = [];
|
|
261
|
-
const CA1Visit = (visited, node) => {
|
|
262
|
-
if (!visited[node]) {
|
|
263
|
-
visited[node] = true;
|
|
264
|
-
node1Ancestors.push(node);
|
|
265
|
-
if (node == node2) {
|
|
266
|
-
lcas.push(node);
|
|
267
|
-
return false; // found - shortcut
|
|
268
|
-
}
|
|
269
|
-
return this.adjacent(node).every(node => {
|
|
270
|
-
return CA1Visit(visited, node);
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
return true;
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
const CA2Visit = (visited, node) => {
|
|
278
|
-
if (!visited[node]) {
|
|
279
|
-
visited[node] = true;
|
|
280
|
-
if (node1Ancestors.indexOf(node) >= 0) {
|
|
281
|
-
lcas.push(node);
|
|
282
|
-
}
|
|
283
|
-
else if (lcas.length == 0) {
|
|
284
|
-
this.adjacent(node).forEach(node => {
|
|
285
|
-
CA2Visit(visited, node);
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
};
|
|
290
|
-
if (CA1Visit({}, node1)) {
|
|
291
|
-
// No shortcut worked
|
|
292
|
-
CA2Visit({}, node2);
|
|
293
|
-
}
|
|
294
|
-
return lcas;
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* The topological sort algorithm yields a list of visited nodes
|
|
298
|
-
* such that for each visited edge (u, v), u comes before v in the list.
|
|
299
|
-
* Amazingly, this comes from just reversing the result from depth first search.
|
|
300
|
-
* Cormen et al. 'Introduction to Algorithms' 3rd Ed. p. 613
|
|
301
|
-
*
|
|
302
|
-
* @param sourceNodes
|
|
303
|
-
* @param includeSourceNodes
|
|
304
|
-
*/
|
|
305
|
-
topologicalSort(sourceNodes, includeSourceNodes = true) {
|
|
306
|
-
return this.depthFirstSearch(sourceNodes, includeSourceNodes, true).reverse();
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* Dijkstra's Shortest Path Algorithm.
|
|
310
|
-
* Cormen et al. 'Introduction to Algorithms' 3rd Ed. p. 658
|
|
311
|
-
* Variable and function names correspond to names in the book.
|
|
312
|
-
*
|
|
313
|
-
* @param source
|
|
314
|
-
* @param destination
|
|
315
|
-
*/
|
|
316
|
-
shortestPath(source, destination) {
|
|
317
|
-
// Upper bounds for shortest path weights from source.
|
|
318
|
-
const d = {};
|
|
319
|
-
// Predecessors.
|
|
320
|
-
const p = {};
|
|
321
|
-
// Poor man's priority queue, keyed on d.
|
|
322
|
-
let q = {};
|
|
323
|
-
const initializeSingleSource = () => {
|
|
324
|
-
this.nodes().forEach((node) => {
|
|
325
|
-
d[node] = Infinity;
|
|
326
|
-
});
|
|
327
|
-
if (d[source] !== Infinity) {
|
|
328
|
-
throw new Error('Source node is not in the graph');
|
|
329
|
-
}
|
|
330
|
-
if (d[destination] !== Infinity) {
|
|
331
|
-
throw new Error('Destination node is not in the graph');
|
|
332
|
-
}
|
|
333
|
-
d[source] = 0;
|
|
334
|
-
};
|
|
335
|
-
// Adds entries in q for all nodes.
|
|
336
|
-
const initializePriorityQueue = () => {
|
|
337
|
-
this.nodes().forEach((node) => {
|
|
338
|
-
q[node] = true;
|
|
339
|
-
});
|
|
340
|
-
};
|
|
341
|
-
// Returns true if q is empty.
|
|
342
|
-
const priorityQueueEmpty = () => {
|
|
343
|
-
return Object.keys(q).length === 0;
|
|
344
|
-
};
|
|
345
|
-
// Linear search to extract (find and remove) min from q.
|
|
346
|
-
const extractMin = () => {
|
|
347
|
-
let min = Infinity;
|
|
348
|
-
let minNode;
|
|
349
|
-
Object.keys(q).forEach((node) => {
|
|
350
|
-
if (d[node] < min) {
|
|
351
|
-
min = d[node];
|
|
352
|
-
minNode = node;
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
if (minNode === undefined) {
|
|
356
|
-
// If we reach here, there's a disconnected subgraph, and we're done.
|
|
357
|
-
q = {};
|
|
358
|
-
return null;
|
|
359
|
-
}
|
|
360
|
-
delete q[minNode];
|
|
361
|
-
return minNode;
|
|
362
|
-
};
|
|
363
|
-
const relax = (u, v) => {
|
|
364
|
-
const w = this.getEdgeWeight(u, v);
|
|
365
|
-
if (d[v] > d[u] + w) {
|
|
366
|
-
d[v] = d[u] + w;
|
|
367
|
-
p[v] = u;
|
|
368
|
-
}
|
|
369
|
-
};
|
|
370
|
-
const dijkstra = () => {
|
|
371
|
-
initializeSingleSource();
|
|
372
|
-
initializePriorityQueue();
|
|
373
|
-
while (!priorityQueueEmpty()) {
|
|
374
|
-
const u = extractMin();
|
|
375
|
-
if (u === null)
|
|
376
|
-
return;
|
|
377
|
-
this.adjacent(u).forEach((v) => {
|
|
378
|
-
relax(u, v);
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
};
|
|
382
|
-
// Assembles the shortest path by traversing the
|
|
383
|
-
// predecessor subgraph from destination to source.
|
|
384
|
-
const path = () => {
|
|
385
|
-
const nodeList = {
|
|
386
|
-
path: [],
|
|
387
|
-
weight: 0,
|
|
388
|
-
};
|
|
389
|
-
let node = destination;
|
|
390
|
-
while (p[node]) {
|
|
391
|
-
nodeList.path.push(node);
|
|
392
|
-
nodeList.weight += this.getEdgeWeight(p[node], node);
|
|
393
|
-
node = p[node];
|
|
394
|
-
}
|
|
395
|
-
if (node !== source) {
|
|
396
|
-
throw new Error('No path found');
|
|
397
|
-
}
|
|
398
|
-
nodeList.path.push(node);
|
|
399
|
-
nodeList.path.reverse();
|
|
400
|
-
// nodeList.weight = 0;
|
|
401
|
-
return nodeList;
|
|
402
|
-
};
|
|
403
|
-
dijkstra();
|
|
404
|
-
return path();
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
* Serializes the graph.
|
|
408
|
-
*/
|
|
409
|
-
serialize() {
|
|
410
|
-
const serialized = {
|
|
411
|
-
nodes: this.nodes().map((id) => {
|
|
412
|
-
return { id: id };
|
|
413
|
-
}),
|
|
414
|
-
links: []
|
|
415
|
-
};
|
|
416
|
-
serialized.nodes.forEach((node) => {
|
|
417
|
-
const source = node.id;
|
|
418
|
-
this.adjacent(source).forEach((target) => {
|
|
419
|
-
serialized.links.push({
|
|
420
|
-
source: source,
|
|
421
|
-
target: target,
|
|
422
|
-
weight: this.getEdgeWeight(source, target)
|
|
423
|
-
});
|
|
424
|
-
});
|
|
425
|
-
});
|
|
426
|
-
return serialized;
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
//# sourceMappingURL=graph.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../../src/lib/container/graph.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,KAAK;IAehB,YAAY,UAAuB;QAdnC;;;;WAIG;QACH,UAAK,GAA6B,EAAE,CAAC;QAErC;;;;WAIG;QACH,gBAAW,GAAoC,EAAE,CAAC;QAGhD,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,UAAsB;QAChC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YAChC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YAChC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,IAAY;QAClB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,CAAS,EAAE,CAAS,EAAE,MAAmB;QAC/C,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAChB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAChB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEzB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAC,CAAS,EAAE,CAAS,EAAE,MAAkB;QACpD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,CAAS,EAAE,CAAS;QAC7B,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAC,IAAY;QACrB,yBAAyB;QACzB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACpC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC1B,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;oBACf,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,qEAAqE;QACrE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,KAAK;QACH,sDAAsD;QACtD,MAAM,OAAO,GAA4B,EAAE,CAAC;QAE5C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACpC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YAClB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC1B,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YACpB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAC,CAAS,EAAE,CAAS;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACvD,OAAO,MAAM,IAAI,CAAC,CAAC;IACrB,CAAC;IAED;;;;;;OAMG;IACH,UAAU,CAAC,CAAS,EAAE,CAAS;QAC7B,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;gBAC7C,OAAO,EAAE,KAAK,CAAC,CAAC;YAClB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,CAAS,EAAE,CAAS;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,IAAY;QACnB,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,SAAS,KAAK,CAAC,CAAS;YACtB,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACf,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACpC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,IAAY;QACpB,OAAO,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC;IAGD;;;;;;;;;;;OAWG;IACH,gBAAgB,CACd,WAA+B,EAC/B,qBAA8B,IAAI,EAClC,eAAwB,KAAK;QAE7B,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,WAAW,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;QAED,IAAI,OAAO,kBAAkB,KAAK,SAAS,EAAE,CAAC;YAC5C,kBAAkB,GAAG,IAAI,CAAC;QAC5B,CAAC;QAED,MAAM,OAAO,GAA4B,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAA4B,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE;YAChC,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,YAAY,EAAE,CAAC;gBACnC,MAAM,IAAI,UAAU,CAAC,aAAa,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;gBACrB,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAE,gCAAgC;gBACxD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACtC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;gBACvB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,kBAAkB,EAAE,CAAC;YACvB,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC3B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACvB,CAAC,CAAC,CAAC;YACH,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC3B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACxC,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAGD;;OAEG;IACH,QAAQ;QACN,IAAI,CAAC;YACH,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAC7C,+BAA+B;YAC/B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC;YACd,CAAC;iBACI,CAAC;gBACJ,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,qBAAqB,CAAC,KAAa,EAAE,KAAa;QAChD,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,MAAM,IAAI,GAAa,EAAE,CAAC;QAE1B,MAAO,QAAQ,GAAG,CAChB,OAAgC,EAChC,IAAY,EACH,EAAE;YACX,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;gBACrB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC;oBAClB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAChB,OAAO,KAAK,CAAC,CAAC,mBAAmB;gBACnC,CAAC;gBACD,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;oBACtC,OAAO,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBACjC,CAAC,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,QAAQ,GAAG,CAAC,OAAgC,EAAE,IAAY,EAAE,EAAE;YAClE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;gBACrB,IAAI,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACtC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClB,CAAC;qBAAM,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;oBAC5B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;wBACjC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBAC1B,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC;YACxB,qBAAqB;YACrB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACtB,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;OAQG;IACH,eAAe,CACb,WAAsB,EACtB,qBAA8B,IAAI;QAElC,OAAO,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;IAChF,CAAC;IAED;;;;;;;OAOG;IACH,YAAY,CAAC,MAAc,EAAE,WAAmB;QAC9C,sDAAsD;QACtD,MAAM,CAAC,GAA+B,EAAE,CAAC;QAEzC,gBAAgB;QAChB,MAAM,CAAC,GAA2B,EAAE,CAAC;QAErC,yCAAyC;QACzC,IAAI,CAAC,GAA4B,EAAE,CAAC;QAEpC,MAAM,sBAAsB,GAAG,GAAG,EAAE;YAClC,IAAI,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC5B,CAAC,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;YACrB,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACrD,CAAC;YACD,IAAI,CAAC,CAAC,WAAW,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAChC,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC1D,CAAC;YACD,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC,CAAC;QAEF,mCAAmC;QACnC,MAAM,uBAAuB,GAAG,GAAG,EAAE;YACnC,IAAI,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC5B,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACjB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,8BAA8B;QAC9B,MAAM,kBAAkB,GAAG,GAAG,EAAE;YAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;QACrC,CAAC,CAAC;QAEF,yDAAyD;QACzD,MAAM,UAAU,GAAG,GAAkB,EAAE;YACrC,IAAI,GAAG,GAAG,QAAQ,CAAC;YACnB,IAAI,OAAO,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC9B,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;oBAClB,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;oBACd,OAAO,GAAG,IAAI,CAAC;gBACjB,CAAC;YACH,CAAC,CAAC,CAAC;YACH,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,qEAAqE;gBACrE,CAAC,GAAG,EAAE,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE;YACrC,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAChB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACX,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,sBAAsB,EAAE,CAAC;YACzB,uBAAuB,EAAE,CAAC;YAC1B,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;gBAC7B,MAAM,CAAC,GAAG,UAAU,EAAE,CAAC;gBACvB,IAAI,CAAC,KAAK,IAAI;oBAAE,OAAO;gBACvB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;oBAC7B,KAAK,CAAC,CAAW,EAAE,CAAC,CAAC,CAAC;gBACxB,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC;QAEF,gDAAgD;QAChD,mDAAmD;QACnD,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,MAAM,QAAQ,GAA2C;gBACvD,IAAI,EAAE,EAAE;gBACR,MAAM,EAAE,CAAC;aACV,CAAC;YACF,IAAI,IAAI,GAAG,WAAW,CAAC;YACvB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBACf,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzB,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;gBACrD,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;YACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;YACnC,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACxB,uBAAuB;YACvB,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC;QAEF,QAAQ,EAAE,CAAC;QAEX,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,SAAS;QACP,MAAM,UAAU,GAAe;YAC7B,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;gBAC7B,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;YACpB,CAAC,CAAC;YACF,KAAK,EAAE,EAAE;SACV,CAAC;QAEF,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YAChC,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;gBACvC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;oBACpB,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC;iBAC3C,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,UAAU,CAAC;IACpB,CAAC;CACF","sourcesContent":["export type NodeId = string;\nexport type EdgeWeight = number;\nexport type EncodedEdge = string;\n\nexport interface Serialized {\n nodes: { id: NodeId }[];\n links: { source: NodeId; target: NodeId; weight: EdgeWeight }[];\n}\n\nexport class CycleError extends Error {\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, CycleError.prototype);\n }\n}\n\n/**\n * A graph data structure with depth-first search and topological sort.\n */\nexport class Graph {\n /**\n * The adjacency list of the graph.\n * Keys are node ids.\n * Values are adjacent node id arrays.\n */\n edges: Record<NodeId, NodeId[]> = {};\n\n /**\n * The weights of edges.\n * Keys are string encodings of edges.\n * Values are weights (numbers).\n */\n edgeWeights: Record<EncodedEdge, EdgeWeight> = {};\n\n constructor(serialized?: Serialized) {\n if (serialized) {\n this.deserialize(serialized);\n }\n }\n\n /**\n * Deserializes the given serialized graph.\n * @param serialized\n */\n deserialize(serialized: Serialized) {\n serialized.nodes.forEach((node) => {\n this.addNode(node.id);\n });\n serialized.links.forEach((link) => {\n this.addEdge(link.source, link.target, link.weight);\n });\n return this;\n }\n\n /**\n * Gets the adjacent node list for the given node.\n * Returns an empty array for unknown nodes.\n * @param node\n */\n adjacent(node: NodeId): NodeId[] {\n return this.edges[node] || [];\n }\n\n /**\n * Adds a node to the graph.\n * If node was already added, this function does nothing.\n * If node was not already added, this function sets up an empty adjacency list.\n * @param node\n */\n addNode(node: NodeId) {\n this.edges[node] = this.adjacent(node);\n return this;\n }\n\n /**\n * Adds an edge from node u to node v.\n * Implicitly adds the nodes if they were not already added.\n * @param u\n * @param v\n * @param weight\n */\n addEdge(u: NodeId, v: NodeId, weight?: EdgeWeight) {\n this.addNode(u);\n this.addNode(v);\n this.adjacent(u).push(v);\n\n if (weight !== undefined) {\n this.setEdgeWeight(u, v, weight);\n }\n\n return this;\n }\n\n /**\n * Sets the weight of the given edge.\n * @param u\n * @param v\n * @param weight\n */\n setEdgeWeight(u: NodeId, v: NodeId, weight: EdgeWeight) {\n this.edgeWeights[this.encodeEdge(u, v)] = weight;\n return this;\n }\n\n /**\n * Computes a string encoding of an edge,\n * for use as a key in an object.\n * @param u\n * @param v\n */\n encodeEdge(u: NodeId, v: NodeId): EncodedEdge {\n return u + '|' + v;\n }\n\n /**\n * Removes a node from the graph.\n * Also removes incoming and outgoing edges.\n * @param node\n */\n removeNode(node: NodeId) {\n // Remove incoming edges.\n Object.keys(this.edges).forEach((u) => {\n this.edges[u].forEach((v) => {\n if (v === node) {\n this.removeEdge(u, v);\n }\n });\n });\n\n // Remove outgoing edges (and signal that the node no longer exists).\n delete this.edges[node];\n\n return this;\n }\n\n /**\n * Gets the list of nodes that have been added to the graph.\n */\n nodes(): NodeId[] {\n // TODO: Better implementation with set data structure\n const nodeSet: Record<NodeId, boolean> = {};\n\n Object.keys(this.edges).forEach((u) => {\n nodeSet[u] = true;\n this.edges[u].forEach((v) => {\n nodeSet[v] = true;\n });\n });\n return Object.keys(nodeSet);\n }\n\n /**\n * Gets the weight of the given edge.\n * Returns 1 if no weight was previously set.\n * @param u\n * @param v\n */\n getEdgeWeight(u: NodeId, v: NodeId): EdgeWeight {\n const weight = this.edgeWeights[this.encodeEdge(u, v)];\n return weight ?? 1;\n }\n\n /**\n * Removes the edge from node u to node v.\n * Does not remove the nodes.\n * Does nothing if the edge does not exist.\n * @param u\n * @param v\n */\n removeEdge(u: NodeId, v: NodeId) {\n if (this.edges[u]) {\n this.edges[u] = this.adjacent(u).filter((_v) => {\n return _v !== v;\n });\n }\n return this;\n }\n\n /**\n * Returns true if there is an edge from node u to node v.\n * @param u\n * @param v\n */\n hasEdge(u: NodeId, v: NodeId) {\n return this.adjacent(u).includes(v);\n }\n\n /**\n * Computes the indegree for the given node.\n * Not very efficient, costs O(E) where E = number of edges.\n *\n * @param node\n */\n inDegree(node: NodeId) {\n let degree = 0;\n function check(v: NodeId) {\n if (v === node) {\n degree++;\n }\n }\n Object.keys(this.edges).forEach((u) => {\n this.edges[u].forEach(check);\n });\n return degree;\n }\n\n /**\n * Computes the outdegree for the given node.\n *\n * @param node\n */\n outDegree(node: NodeId) {\n return node in this.edges ? this.edges[node].length : 0;\n }\n\n\n /**\n * Depth First Search algorithm, inspired by\n * Cormen et al. 'Introduction to Algorithms' 3rd Ed. p. 604\n * The additional option `includeSourceNodes` specifies whether to\n * include or exclude the source nodes from the result (true by default).\n * If `sourceNodes` is not specified, all nodes in the graph\n * are used as source nodes.\n *\n * @param sourceNodes\n * @param includeSourceNodes\n * @param errorOnCycle\n */\n depthFirstSearch(\n sourceNodes: NodeId[]|undefined,\n includeSourceNodes: boolean = true,\n errorOnCycle: boolean = false,\n ) {\n if (!sourceNodes) {\n sourceNodes = this.nodes();\n }\n\n if (typeof includeSourceNodes !== 'boolean') {\n includeSourceNodes = true;\n }\n\n const visited: Record<NodeId, boolean> = {};\n const visiting: Record<NodeId, boolean> = {};\n const nodeList: NodeId[] = [];\n\n const DFSVisit = (node: NodeId) => {\n if (visiting[node] && errorOnCycle) {\n throw new CycleError('Cycle found');\n }\n if (!visited[node]) {\n visited[node] = true;\n visiting[node] = true; // temporary flag while visiting\n this.adjacent(node).forEach(DFSVisit);\n visiting[node] = false;\n nodeList.push(node);\n }\n };\n\n if (includeSourceNodes) {\n sourceNodes.forEach(DFSVisit);\n } else {\n sourceNodes.forEach((node) => {\n visited[node] = true;\n });\n sourceNodes.forEach((node) => {\n this.adjacent(node).forEach(DFSVisit);\n });\n }\n\n return nodeList;\n }\n\n\n /**\n * Returns true if the graph has one or more cycles and false otherwise\n */\n hasCycle(): boolean {\n try {\n this.depthFirstSearch(undefined, true, true);\n // No error thrown -> no cycles\n return false;\n }\n catch (error) {\n if (error instanceof CycleError) {\n return true;\n }\n else {\n throw error;\n }\n }\n }\n\n /**\n * Least Common Ancestors\n * Inspired by https://github.com/relaxedws/lca/blob/master/src/LowestCommonAncestor.php code\n * but uses depth search instead of breadth. Also uses some optimizations\n *\n * @param node1\n * @param node2\n */\n lowestCommonAncestors(node1: NodeId, node2: NodeId) {\n const node1Ancestors: NodeId[] = [];\n const lcas: NodeId[] = [];\n\n const CA1Visit = (\n visited: Record<NodeId, boolean>,\n node: NodeId\n ): boolean => {\n if (!visited[node]) {\n visited[node] = true;\n node1Ancestors.push(node);\n if (node == node2) {\n lcas.push(node);\n return false; // found - shortcut\n }\n return this.adjacent(node).every(node => {\n return CA1Visit(visited, node);\n });\n } else {\n return true;\n }\n };\n\n const CA2Visit = (visited: Record<NodeId, boolean>, node: NodeId) => {\n if (!visited[node]) {\n visited[node] = true;\n if (node1Ancestors.indexOf(node) >= 0) {\n lcas.push(node);\n } else if (lcas.length == 0) {\n this.adjacent(node).forEach(node => {\n CA2Visit(visited, node);\n });\n }\n }\n };\n\n if (CA1Visit({}, node1)) {\n // No shortcut worked\n CA2Visit({}, node2);\n }\n\n return lcas;\n }\n\n /**\n * The topological sort algorithm yields a list of visited nodes\n * such that for each visited edge (u, v), u comes before v in the list.\n * Amazingly, this comes from just reversing the result from depth first search.\n * Cormen et al. 'Introduction to Algorithms' 3rd Ed. p. 613\n *\n * @param sourceNodes\n * @param includeSourceNodes\n */\n topologicalSort(\n sourceNodes?: NodeId[],\n includeSourceNodes: boolean = true\n ) {\n return this.depthFirstSearch(sourceNodes, includeSourceNodes, true).reverse();\n }\n\n /**\n * Dijkstra's Shortest Path Algorithm.\n * Cormen et al. 'Introduction to Algorithms' 3rd Ed. p. 658\n * Variable and function names correspond to names in the book.\n *\n * @param source\n * @param destination\n */\n shortestPath(source: NodeId, destination: NodeId) {\n // Upper bounds for shortest path weights from source.\n const d: Record<NodeId, EdgeWeight> = {};\n\n // Predecessors.\n const p: Record<NodeId, NodeId> = {};\n\n // Poor man's priority queue, keyed on d.\n let q: Record<NodeId, boolean> = {};\n\n const initializeSingleSource = () => {\n this.nodes().forEach((node) => {\n d[node] = Infinity;\n });\n if (d[source] !== Infinity) {\n throw new Error('Source node is not in the graph');\n }\n if (d[destination] !== Infinity) {\n throw new Error('Destination node is not in the graph');\n }\n d[source] = 0;\n };\n\n // Adds entries in q for all nodes.\n const initializePriorityQueue = () => {\n this.nodes().forEach((node) => {\n q[node] = true;\n });\n };\n\n // Returns true if q is empty.\n const priorityQueueEmpty = () => {\n return Object.keys(q).length === 0;\n };\n\n // Linear search to extract (find and remove) min from q.\n const extractMin = (): NodeId | null => {\n let min = Infinity;\n let minNode;\n Object.keys(q).forEach((node) => {\n if (d[node] < min) {\n min = d[node];\n minNode = node;\n }\n });\n if (minNode === undefined) {\n // If we reach here, there's a disconnected subgraph, and we're done.\n q = {};\n return null;\n }\n delete q[minNode];\n return minNode;\n };\n\n const relax = (u: NodeId, v: NodeId) => {\n const w = this.getEdgeWeight(u, v);\n if (d[v] > d[u] + w) {\n d[v] = d[u] + w;\n p[v] = u;\n }\n };\n\n const dijkstra = () => {\n initializeSingleSource();\n initializePriorityQueue();\n while (!priorityQueueEmpty()) {\n const u = extractMin();\n if (u === null) return;\n this.adjacent(u).forEach((v) => {\n relax(u as string, v);\n });\n }\n };\n\n // Assembles the shortest path by traversing the\n // predecessor subgraph from destination to source.\n const path = () => {\n const nodeList: { path: NodeId[], weight: EdgeWeight } = {\n path: [],\n weight: 0,\n };\n let node = destination;\n while (p[node]) {\n nodeList.path.push(node);\n nodeList.weight += this.getEdgeWeight(p[node], node);\n node = p[node];\n }\n if (node !== source) {\n throw new Error('No path found');\n }\n nodeList.path.push(node);\n nodeList.path.reverse();\n // nodeList.weight = 0;\n return nodeList;\n };\n\n dijkstra();\n\n return path();\n }\n\n /**\n * Serializes the graph.\n */\n serialize() {\n const serialized: Serialized = {\n nodes: this.nodes().map((id) => {\n return { id: id };\n }),\n links: []\n };\n\n serialized.nodes.forEach((node) => {\n const source = node.id;\n this.adjacent(source).forEach((target) => {\n serialized.links.push({\n source: source,\n target: target,\n weight: this.getEdgeWeight(source, target)\n });\n });\n });\n\n return serialized;\n }\n}\n"]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Class } from 'utility-types';
|
|
2
|
-
export declare function Inject<K extends Class<unknown>>(klass: K): ParameterDecorator;
|
|
3
|
-
export declare function getInjectMetadata(target: any): {
|
|
4
|
-
parameterIndex: number;
|
|
5
|
-
klass: Class<unknown>;
|
|
6
|
-
}[];
|
|
7
|
-
//# sourceMappingURL=inject.decorator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inject.decorator.d.ts","sourceRoot":"","sources":["../../../src/lib/injctable/inject.decorator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAUtC,wBAAgB,MAAM,CAAC,CAAC,SAAS,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,kBAAkB,CA+B7E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,GAAG,GAAG;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;CAAC,EAAE,CAEhG"}
|