@appland/scanner 1.54.1 → 1.57.0
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/CHANGELOG.md +31 -0
- package/built/algorithms/dataStructures/graph/Graph.js +53 -62
- package/built/algorithms/dataStructures/graph/GraphEdge.js +13 -16
- package/built/algorithms/dataStructures/graph/GraphVertex.js +37 -42
- package/built/algorithms/dataStructures/linked-list/LinkedList.js +33 -38
- package/built/algorithms/dataStructures/linked-list/LinkedListNode.js +6 -10
- package/built/algorithms/graph/depth-first-search/index.js +7 -8
- package/built/algorithms/graph/detect-cycle/index.js +15 -16
- package/built/algorithms/utils/Comparator.js +19 -21
- package/built/analyzer/recordSecrets.js +7 -30
- package/built/analyzer/secretsRegexes.js +8 -9
- package/built/appMapIndex.js +18 -20
- package/built/check.js +16 -18
- package/built/checkInstance.js +26 -48
- package/built/cli/ci/command.js +61 -147
- package/built/cli/ci/options.js +0 -1
- package/built/cli/codeVersionArgs.js +0 -1
- package/built/cli/exitCode.js +0 -1
- package/built/cli/fail.js +2 -3
- package/built/cli/merge/command.js +21 -63
- package/built/cli/merge/options.js +0 -1
- package/built/cli/reportUploadURL.js +2 -3
- package/built/cli/resolveAppId.js +34 -85
- package/built/cli/scan/command.js +58 -233
- package/built/cli/scan/formatReport.js +44 -0
- package/built/cli/scan/options.js +0 -1
- package/built/cli/scan/scanner.js +38 -117
- package/built/cli/scan/singleScan.js +80 -0
- package/built/cli/scan/watchScan.js +84 -0
- package/built/cli/scan.js +39 -132
- package/built/cli/scanArgs.js +2 -4
- package/built/cli/scanOptions.js +0 -1
- package/built/cli/updateCommitStatus.js +10 -47
- package/built/cli/upload/command.js +21 -65
- package/built/cli/upload/options.js +0 -1
- package/built/cli/upload/pruneAppMap.js +16 -0
- package/built/cli/upload.js +91 -172
- package/built/cli/validateFile.js +13 -48
- package/built/cli.js +34 -21
- package/built/configuration/configurationProvider.js +148 -227
- package/built/configuration/schema/options.json +76 -76
- package/built/configuration/types/checkConfig.js +0 -1
- package/built/configuration/types/configuration.js +0 -1
- package/built/configuration/types/matchEventConfig.js +0 -1
- package/built/configuration/types/matchPatternConfig.js +0 -1
- package/built/database/index.js +33 -127
- package/built/database/visit.js +16 -66
- package/built/errors.js +4 -30
- package/built/eventUtil.js +10 -35
- package/built/findings.js +3 -4
- package/built/integration/appland/app/exists.js +33 -76
- package/built/integration/appland/app/listFindingStatus.js +5 -38
- package/built/integration/appland/appMap/create.js +38 -89
- package/built/integration/appland/location.js +0 -1
- package/built/integration/appland/mapset/create.js +34 -85
- package/built/integration/appland/retry.js +10 -11
- package/built/integration/appland/retryOptions.js +0 -1
- package/built/integration/appland/scannerJob/create.js +34 -84
- package/built/integration/appland/scannerJob/merge.js +28 -74
- package/built/integration/appland/scannerJob.js +0 -1
- package/built/integration/github/commitStatus.js +3 -4
- package/built/integration/vars.js +1 -2
- package/built/openapi/index.js +39 -83
- package/built/report/appMapMetadata.js +0 -1
- package/built/report/findingSummary.js +0 -1
- package/built/report/findingsReport.js +14 -16
- package/built/report/scanResults.js +18 -45
- package/built/report/scanSummary.js +0 -1
- package/built/report/summaryReport.js +12 -13
- package/built/ruleChecker.js +146 -297
- package/built/rules/authzBeforeAuthn.js +25 -59
- package/built/rules/circularDependency.js +69 -101
- package/built/rules/deserializationOfUntrustedData.js +29 -63
- package/built/rules/execOfUntrustedCommand.js +28 -62
- package/built/rules/http-500/metadata.js +0 -1
- package/built/rules/http-500/rule.js +2 -3
- package/built/rules/illegalPackageDependency.js +16 -18
- package/built/rules/incompatibleHttpClientRequest.js +30 -69
- package/built/rules/insecureCompare.js +12 -13
- package/built/rules/jobNotCancelled.js +13 -45
- package/built/rules/lib/hasParameterOrReceiver.js +4 -7
- package/built/rules/lib/matchEvent.js +12 -13
- package/built/rules/lib/matchPattern.js +6 -7
- package/built/rules/lib/metadata.js +0 -1
- package/built/rules/lib/parseRuleDescription.js +5 -6
- package/built/rules/lib/precedingEvents.js +7 -75
- package/built/rules/lib/rpcWithoutProtection.js +5 -28
- package/built/rules/lib/sanitizesData.js +0 -1
- package/built/rules/lib/util.js +48 -25
- package/built/rules/logoutWithoutSessionReset.js +24 -58
- package/built/rules/missingAuthentication.js +28 -28
- package/built/rules/missingContentType.js +8 -9
- package/built/rules/nPlusOneQuery.js +35 -87
- package/built/rules/queryFromInvalidPackage.js +17 -19
- package/built/rules/queryFromView.js +13 -16
- package/built/rules/rpcWithoutCircuitBreaker.js +14 -84
- package/built/rules/saveWithoutValidation.js +8 -9
- package/built/rules/secretInLog.js +30 -93
- package/built/rules/slowFunctionCall.js +16 -20
- package/built/rules/slowHttpServerRequest.js +9 -11
- package/built/rules/slowQuery.js +9 -12
- package/built/rules/tooManyJoins.js +26 -51
- package/built/rules/tooManyUpdates.js +25 -105
- package/built/rules/unbatchedMaterializedQuery.js +26 -30
- package/built/rules/updateInGetRequest.js +30 -45
- package/built/scope/commandScope.js +24 -144
- package/built/scope/httpClientRequestScope.js +11 -98
- package/built/scope/httpServerRequestScope.js +11 -98
- package/built/scope/rootScope.js +11 -98
- package/built/scope/scopeImpl.js +10 -82
- package/built/scope/scopeIterator.js +6 -10
- package/built/scope/sqlTransactionScope.js +24 -122
- package/built/sqlWarning.js +9 -35
- package/built/telemetry.js +215 -0
- package/built/wellKnownLabels.js +0 -1
- package/package.json +10 -4
- package/built/algorithms/dataStructures/graph/Graph.js.map +0 -1
- package/built/algorithms/dataStructures/graph/GraphEdge.js.map +0 -1
- package/built/algorithms/dataStructures/graph/GraphVertex.js.map +0 -1
- package/built/algorithms/dataStructures/linked-list/LinkedList.js.map +0 -1
- package/built/algorithms/dataStructures/linked-list/LinkedListNode.js.map +0 -1
- package/built/algorithms/graph/depth-first-search/index.js.map +0 -1
- package/built/algorithms/graph/detect-cycle/index.js.map +0 -1
- package/built/algorithms/utils/Comparator.js.map +0 -1
- package/built/analyzer/recordSecrets.js.map +0 -1
- package/built/analyzer/secretsRegexes.js.map +0 -1
- package/built/appMapIndex.js.map +0 -1
- package/built/check.js.map +0 -1
- package/built/checkInstance.js.map +0 -1
- package/built/cli/ci/command.js.map +0 -1
- package/built/cli/ci/options.js.map +0 -1
- package/built/cli/codeVersionArgs.js.map +0 -1
- package/built/cli/exitCode.js.map +0 -1
- package/built/cli/fail.js.map +0 -1
- package/built/cli/merge/command.js.map +0 -1
- package/built/cli/merge/options.js.map +0 -1
- package/built/cli/reportUploadURL.js.map +0 -1
- package/built/cli/resolveAppId.js.map +0 -1
- package/built/cli/scan/command.js.map +0 -1
- package/built/cli/scan/options.js.map +0 -1
- package/built/cli/scan/scanner.js.map +0 -1
- package/built/cli/scan.js.map +0 -1
- package/built/cli/scanArgs.js.map +0 -1
- package/built/cli/scanOptions.js.map +0 -1
- package/built/cli/updateCommitStatus.js.map +0 -1
- package/built/cli/upload/command.js.map +0 -1
- package/built/cli/upload/options.js.map +0 -1
- package/built/cli/upload.js.map +0 -1
- package/built/cli/validateFile.js.map +0 -1
- package/built/cli.js.map +0 -1
- package/built/configuration/configurationProvider.js.map +0 -1
- package/built/configuration/types/checkConfig.js.map +0 -1
- package/built/configuration/types/configuration.js.map +0 -1
- package/built/configuration/types/matchEventConfig.js.map +0 -1
- package/built/configuration/types/matchPatternConfig.js.map +0 -1
- package/built/database/index.js.map +0 -1
- package/built/database/visit.js.map +0 -1
- package/built/errors.js.map +0 -1
- package/built/eventUtil.js.map +0 -1
- package/built/findings.js.map +0 -1
- package/built/integration/appland/app/exists.js.map +0 -1
- package/built/integration/appland/app/listFindingStatus.js.map +0 -1
- package/built/integration/appland/appMap/create.js.map +0 -1
- package/built/integration/appland/location.js.map +0 -1
- package/built/integration/appland/mapset/create.js.map +0 -1
- package/built/integration/appland/retry.js.map +0 -1
- package/built/integration/appland/retryOptions.js.map +0 -1
- package/built/integration/appland/scannerJob/create.js.map +0 -1
- package/built/integration/appland/scannerJob/merge.js.map +0 -1
- package/built/integration/appland/scannerJob.js.map +0 -1
- package/built/integration/github/commitStatus.js.map +0 -1
- package/built/integration/vars.js.map +0 -1
- package/built/openapi/index.js.map +0 -1
- package/built/openapi/method.js +0 -120
- package/built/openapi/method.js.map +0 -1
- package/built/openapi/model.js +0 -49
- package/built/openapi/model.js.map +0 -1
- package/built/openapi/path.js +0 -36
- package/built/openapi/path.js.map +0 -1
- package/built/openapi/provider.js +0 -133
- package/built/openapi/provider.js.map +0 -1
- package/built/openapi/response.js +0 -59
- package/built/openapi/response.js.map +0 -1
- package/built/openapi/rpcRequest.js +0 -130
- package/built/openapi/rpcRequest.js.map +0 -1
- package/built/openapi/schema.js +0 -42
- package/built/openapi/schema.js.map +0 -1
- package/built/openapi/securitySchemes.js +0 -32
- package/built/openapi/securitySchemes.js.map +0 -1
- package/built/openapi/statusCodes.js +0 -68
- package/built/openapi/statusCodes.js.map +0 -1
- package/built/openapi/util.js +0 -91
- package/built/openapi/util.js.map +0 -1
- package/built/report/appMapMetadata.js.map +0 -1
- package/built/report/findingSummary.js.map +0 -1
- package/built/report/findingsReport.js.map +0 -1
- package/built/report/scanResults.js.map +0 -1
- package/built/report/scanSummary.js.map +0 -1
- package/built/report/summaryReport.js.map +0 -1
- package/built/ruleChecker.js.map +0 -1
- package/built/rules/authzBeforeAuthn.js.map +0 -1
- package/built/rules/circularDependency.js.map +0 -1
- package/built/rules/deserializationOfUntrustedData.js.map +0 -1
- package/built/rules/execOfUntrustedCommand.js.map +0 -1
- package/built/rules/http-500/metadata.js.map +0 -1
- package/built/rules/http-500/rule.js.map +0 -1
- package/built/rules/illegalPackageDependency.js.map +0 -1
- package/built/rules/incompatibleHttpClientRequest.js.map +0 -1
- package/built/rules/insecureCompare.js.map +0 -1
- package/built/rules/jobNotCancelled.js.map +0 -1
- package/built/rules/lib/hasParameterOrReceiver.js.map +0 -1
- package/built/rules/lib/matchEvent.js.map +0 -1
- package/built/rules/lib/matchPattern.js.map +0 -1
- package/built/rules/lib/metadata.js.map +0 -1
- package/built/rules/lib/parseRuleDescription.js.map +0 -1
- package/built/rules/lib/precedingEvents.js.map +0 -1
- package/built/rules/lib/rpcWithoutProtection.js.map +0 -1
- package/built/rules/lib/sanitizesData.js.map +0 -1
- package/built/rules/lib/util.js.map +0 -1
- package/built/rules/logoutWithoutSessionReset.js.map +0 -1
- package/built/rules/missingAuthentication.js.map +0 -1
- package/built/rules/missingContentType.js.map +0 -1
- package/built/rules/nPlusOneQuery.js.map +0 -1
- package/built/rules/queryFromInvalidPackage.js.map +0 -1
- package/built/rules/queryFromView.js.map +0 -1
- package/built/rules/rpcWithoutCircuitBreaker.js.map +0 -1
- package/built/rules/saveWithoutValidation.js.map +0 -1
- package/built/rules/secretInLog.js.map +0 -1
- package/built/rules/slowFunctionCall.js.map +0 -1
- package/built/rules/slowHttpServerRequest.js.map +0 -1
- package/built/rules/slowQuery.js.map +0 -1
- package/built/rules/tooManyJoins.js.map +0 -1
- package/built/rules/tooManyUpdates.js.map +0 -1
- package/built/rules/unbatchedMaterializedQuery.js.map +0 -1
- package/built/rules/updateInGetRequest.js.map +0 -1
- package/built/scope/commandScope.js.map +0 -1
- package/built/scope/httpClientRequestScope.js.map +0 -1
- package/built/scope/httpServerRequestScope.js.map +0 -1
- package/built/scope/rootScope.js.map +0 -1
- package/built/scope/scopeImpl.js.map +0 -1
- package/built/scope/scopeIterator.js.map +0 -1
- package/built/scope/sqlTransactionScope.js.map +0 -1
- package/built/sqlWarning.js.map +0 -1
- package/built/wellKnownLabels.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
# [@appland/scanner-v1.57.0](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.56.1...@appland/scanner-v1.57.0) (2022-05-23)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Collect scanning telemetry ([adc71b7](https://github.com/applandinc/appmap-js/commit/adc71b7d43ae302ac3b85b8577a01bdcfa0176ea))
|
|
7
|
+
* Send telemetry on scanning errors ([0828a8a](https://github.com/applandinc/appmap-js/commit/0828a8a5a61247ab923e2fe9b302970accd3b10d))
|
|
8
|
+
|
|
9
|
+
# [@appland/scanner-v1.56.1](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.56.0...@appland/scanner-v1.56.1) (2022-05-16)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* Have scanner prune AppMaps before uploading ([1de9f55](https://github.com/applandinc/appmap-js/commit/1de9f55fa25668a8bfe95def458bf8d5aa7dbae3))
|
|
15
|
+
|
|
16
|
+
# [@appland/scanner-v1.56.0](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.55.0...@appland/scanner-v1.56.0) (2022-05-11)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* Add --watch flag to scan command ([51cb6fc](https://github.com/applandinc/appmap-js/commit/51cb6fc168e1b416587077e26c09d4e54dc9565b))
|
|
22
|
+
|
|
23
|
+
# [@appland/scanner-v1.55.0](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.54.1...@appland/scanner-v1.55.0) (2022-05-10)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Features
|
|
27
|
+
|
|
28
|
+
* Change default file names ([e173fbb](https://github.com/applandinc/appmap-js/commit/e173fbbe464c8076133f91e04ecdb531dd80c13f))
|
|
29
|
+
* Read appmap_dir from appmap.yml ([b0b6b0d](https://github.com/applandinc/appmap-js/commit/b0b6b0db45eec8c0b8fa96d0f3005677a43f813b))
|
|
30
|
+
* Support repeated appmap-file option ([62edf68](https://github.com/applandinc/appmap-js/commit/62edf68a00d2e169cfbfed5e63246b5fbec947d7))
|
|
31
|
+
|
|
1
32
|
# [@appland/scanner-v1.54.1](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.54.0...@appland/scanner-v1.54.1) (2022-05-03)
|
|
2
33
|
|
|
3
34
|
|
|
@@ -1,44 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
class Graph {
|
|
4
4
|
/**
|
|
5
5
|
* @param {boolean} isDirected
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
if (isDirected === void 0) { isDirected = false; }
|
|
7
|
+
constructor(isDirected = false) {
|
|
9
8
|
this.vertices = {};
|
|
10
9
|
this.edges = {};
|
|
11
10
|
this.vertices = {};
|
|
12
11
|
this.edges = {};
|
|
13
12
|
this.isDirected = isDirected;
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
enumerable: false,
|
|
20
|
-
configurable: true
|
|
21
|
-
});
|
|
22
|
-
Graph.prototype.addVertex = function (newVertex) {
|
|
14
|
+
get vertexCount() {
|
|
15
|
+
return Object.keys(this.vertices).length;
|
|
16
|
+
}
|
|
17
|
+
addVertex(newVertex) {
|
|
23
18
|
this.vertices[newVertex.getKey()] = newVertex;
|
|
24
19
|
return this;
|
|
25
|
-
}
|
|
26
|
-
|
|
20
|
+
}
|
|
21
|
+
getVertexByKey(vertexKey) {
|
|
27
22
|
return this.vertices[vertexKey];
|
|
28
|
-
}
|
|
29
|
-
|
|
23
|
+
}
|
|
24
|
+
getNeighbors(vertex) {
|
|
30
25
|
return vertex.getNeighbors();
|
|
31
|
-
}
|
|
32
|
-
|
|
26
|
+
}
|
|
27
|
+
getAllVertices() {
|
|
33
28
|
return Object.values(this.vertices);
|
|
34
|
-
}
|
|
35
|
-
|
|
29
|
+
}
|
|
30
|
+
getAllEdges() {
|
|
36
31
|
return Object.values(this.edges);
|
|
37
|
-
}
|
|
38
|
-
|
|
32
|
+
}
|
|
33
|
+
addEdge(edge) {
|
|
39
34
|
// Try to find and end start vertices.
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
let startVertex = this.getVertexByKey(edge.startVertex.getKey());
|
|
36
|
+
let endVertex = this.getVertexByKey(edge.endVertex.getKey());
|
|
42
37
|
// Insert start vertex if it wasn't inserted.
|
|
43
38
|
if (!startVertex) {
|
|
44
39
|
this.addVertex(edge.startVertex);
|
|
@@ -67,8 +62,8 @@ var Graph = /** @class */ (function () {
|
|
|
67
62
|
endVertex.addEdge(edge);
|
|
68
63
|
}
|
|
69
64
|
return this;
|
|
70
|
-
}
|
|
71
|
-
|
|
65
|
+
}
|
|
66
|
+
deleteEdge(edge) {
|
|
72
67
|
// Delete edge from the list of edges.
|
|
73
68
|
if (this.edges[edge.getKey()]) {
|
|
74
69
|
delete this.edges[edge.getKey()];
|
|
@@ -77,79 +72,75 @@ var Graph = /** @class */ (function () {
|
|
|
77
72
|
throw new Error('Edge not found in graph');
|
|
78
73
|
}
|
|
79
74
|
// Try to find and end start vertices and delete edge from them.
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
const startVertex = this.getVertexByKey(edge.startVertex.getKey());
|
|
76
|
+
const endVertex = this.getVertexByKey(edge.endVertex.getKey());
|
|
82
77
|
if (startVertex) {
|
|
83
78
|
startVertex.deleteEdge(edge);
|
|
84
79
|
}
|
|
85
80
|
if (endVertex) {
|
|
86
81
|
endVertex.deleteEdge(edge);
|
|
87
82
|
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
}
|
|
84
|
+
findEdge(startVertex, endVertex) {
|
|
85
|
+
const vertex = this.getVertexByKey(startVertex.getKey());
|
|
91
86
|
if (!vertex) {
|
|
92
87
|
return null;
|
|
93
88
|
}
|
|
94
89
|
return vertex.findEdge(endVertex);
|
|
95
|
-
}
|
|
96
|
-
|
|
90
|
+
}
|
|
91
|
+
findVertexByKey(vertexKey) {
|
|
97
92
|
if (this.vertices[vertexKey]) {
|
|
98
93
|
return this.vertices[vertexKey];
|
|
99
94
|
}
|
|
100
95
|
return null;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return this.getAllEdges().reduce(
|
|
96
|
+
}
|
|
97
|
+
getWeight() {
|
|
98
|
+
return this.getAllEdges().reduce((weight, graphEdge) => {
|
|
104
99
|
return weight + graphEdge.weight;
|
|
105
100
|
}, 0);
|
|
106
|
-
}
|
|
101
|
+
}
|
|
107
102
|
/**
|
|
108
103
|
* Reverse all the edges in directed graph.
|
|
109
104
|
*/
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
this.getAllEdges().forEach(function (edge) {
|
|
105
|
+
reverse() {
|
|
106
|
+
this.getAllEdges().forEach((edge) => {
|
|
113
107
|
// Delete straight edge from graph and from vertices.
|
|
114
|
-
|
|
108
|
+
this.deleteEdge(edge);
|
|
115
109
|
// Reverse the edge.
|
|
116
110
|
edge.reverse();
|
|
117
111
|
// Add reversed edge back to the graph and its vertices.
|
|
118
|
-
|
|
112
|
+
this.addEdge(edge);
|
|
119
113
|
});
|
|
120
114
|
return this;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
this.getAllVertices().forEach(
|
|
115
|
+
}
|
|
116
|
+
getVerticesIndices() {
|
|
117
|
+
const verticesIndices = {};
|
|
118
|
+
this.getAllVertices().forEach((vertex, index) => {
|
|
125
119
|
verticesIndices[vertex.getKey()] = index;
|
|
126
120
|
});
|
|
127
121
|
return verticesIndices;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
var verticesIndices = this.getVerticesIndices();
|
|
122
|
+
}
|
|
123
|
+
getAdjacencyMatrix() {
|
|
124
|
+
const vertices = this.getAllVertices();
|
|
125
|
+
const verticesIndices = this.getVerticesIndices();
|
|
133
126
|
// Init matrix with infinities meaning that there is no ways of
|
|
134
127
|
// getting from one vertex to another yet.
|
|
135
|
-
|
|
128
|
+
const adjacencyMatrix = Array(vertices.length)
|
|
136
129
|
.fill(null)
|
|
137
|
-
.map(
|
|
130
|
+
.map(() => {
|
|
138
131
|
return Array(vertices.length).fill(Infinity);
|
|
139
132
|
});
|
|
140
133
|
// Fill the columns.
|
|
141
|
-
vertices.forEach(
|
|
142
|
-
vertex.getNeighbors().forEach(
|
|
143
|
-
|
|
144
|
-
adjacencyMatrix[vertexIndex][neighborIndex] =
|
|
134
|
+
vertices.forEach((vertex, vertexIndex) => {
|
|
135
|
+
vertex.getNeighbors().forEach((neighbor) => {
|
|
136
|
+
const neighborIndex = verticesIndices[neighbor.getKey()];
|
|
137
|
+
adjacencyMatrix[vertexIndex][neighborIndex] = this.findEdge(vertex, neighbor).weight;
|
|
145
138
|
});
|
|
146
139
|
});
|
|
147
140
|
return adjacencyMatrix;
|
|
148
|
-
}
|
|
149
|
-
|
|
141
|
+
}
|
|
142
|
+
toString() {
|
|
150
143
|
return Object.keys(this.vertices).toString();
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
}());
|
|
144
|
+
}
|
|
145
|
+
}
|
|
154
146
|
exports.default = Graph;
|
|
155
|
-
//# sourceMappingURL=Graph.js.map
|
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (weight === void 0) { weight = 0; }
|
|
3
|
+
class GraphEdge {
|
|
4
|
+
constructor(startVertex, endVertex, weight = 0) {
|
|
6
5
|
this.startVertex = startVertex;
|
|
7
6
|
this.endVertex = endVertex;
|
|
8
7
|
this.weight = weight;
|
|
9
8
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
getKey() {
|
|
10
|
+
const startVertexKey = this.startVertex.getKey();
|
|
11
|
+
const endVertexKey = this.endVertex.getKey();
|
|
12
|
+
return `${startVertexKey} - ${endVertexKey}`;
|
|
13
|
+
}
|
|
14
|
+
reverse() {
|
|
15
|
+
const tmp = this.startVertex;
|
|
17
16
|
this.startVertex = this.endVertex;
|
|
18
17
|
this.endVertex = tmp;
|
|
19
18
|
return this;
|
|
20
|
-
}
|
|
21
|
-
|
|
19
|
+
}
|
|
20
|
+
toString() {
|
|
22
21
|
return this.getKey();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
}());
|
|
22
|
+
}
|
|
23
|
+
}
|
|
26
24
|
exports.default = GraphEdge;
|
|
27
|
-
//# sourceMappingURL=GraphEdge.js.map
|
|
@@ -3,16 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const LinkedList_1 = __importDefault(require("../linked-list/LinkedList"));
|
|
7
|
+
class GraphVertex {
|
|
8
8
|
/**
|
|
9
9
|
* @param {*} value
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
constructor(value) {
|
|
12
12
|
if (value === '') {
|
|
13
13
|
throw new Error('Graph vertex must have a non-empty value');
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
const edgeComparator = (edgeA, edgeB) => {
|
|
16
16
|
if (edgeA.getKey() === edgeB.getKey()) {
|
|
17
17
|
return 0;
|
|
18
18
|
}
|
|
@@ -23,57 +23,52 @@ var GraphVertex = /** @class */ (function () {
|
|
|
23
23
|
this.value = value;
|
|
24
24
|
this.edges = new LinkedList_1.default(edgeComparator);
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
addEdge(edge) {
|
|
27
27
|
this.edges.append(edge);
|
|
28
28
|
return this;
|
|
29
|
-
}
|
|
30
|
-
|
|
29
|
+
}
|
|
30
|
+
deleteEdge(edge) {
|
|
31
31
|
this.edges.delete(edge);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return node.value.startVertex === _this ? node.value.endVertex : node.value.startVertex;
|
|
32
|
+
}
|
|
33
|
+
getNeighbors() {
|
|
34
|
+
const edges = this.edges.toArray();
|
|
35
|
+
const neighborsConverter = (node) => {
|
|
36
|
+
return node.value.startVertex === this ? node.value.endVertex : node.value.startVertex;
|
|
38
37
|
};
|
|
39
38
|
// Return either start or end vertex.
|
|
40
39
|
// For undirected graphs it is possible that current vertex will be the end one.
|
|
41
40
|
return edges.map(neighborsConverter);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return this.edges.toArray().map(
|
|
45
|
-
}
|
|
46
|
-
|
|
41
|
+
}
|
|
42
|
+
getEdges() {
|
|
43
|
+
return this.edges.toArray().map((linkedListNode) => linkedListNode.value);
|
|
44
|
+
}
|
|
45
|
+
getDegree() {
|
|
47
46
|
return this.edges.toArray().length;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
}
|
|
48
|
+
hasEdge(requiredEdge) {
|
|
49
|
+
const edgeNode = this.edges.find(undefined, (edge) => edge === requiredEdge);
|
|
51
50
|
return !!edgeNode;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
}
|
|
52
|
+
hasNeighbor(vertex) {
|
|
53
|
+
const vertexNode = this.edges.find(undefined, (edge) => edge.startVertex === vertex || edge.endVertex === vertex);
|
|
55
54
|
return !!vertexNode;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
}
|
|
56
|
+
findEdge(vertex) {
|
|
57
|
+
const edgeFinder = (edge) => {
|
|
59
58
|
return edge.startVertex === vertex || edge.endVertex === vertex;
|
|
60
59
|
};
|
|
61
|
-
|
|
60
|
+
const edge = this.edges.find(undefined, edgeFinder);
|
|
62
61
|
return edge ? edge.value : null;
|
|
63
|
-
}
|
|
64
|
-
|
|
62
|
+
}
|
|
63
|
+
getKey() {
|
|
65
64
|
return this.value;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.getEdges().forEach(function (edge) { return _this.deleteEdge(edge); });
|
|
65
|
+
}
|
|
66
|
+
deleteAllEdges() {
|
|
67
|
+
this.getEdges().forEach((edge) => this.deleteEdge(edge));
|
|
70
68
|
return this;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return GraphVertex;
|
|
77
|
-
}());
|
|
69
|
+
}
|
|
70
|
+
toString(callback = undefined) {
|
|
71
|
+
return callback ? callback(this.value) : `${this.value}`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
78
74
|
exports.default = GraphVertex;
|
|
79
|
-
//# sourceMappingURL=GraphVertex.js.map
|
|
@@ -3,21 +3,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const LinkedListNode_1 = __importDefault(require("./LinkedListNode"));
|
|
7
|
+
const Comparator_1 = __importDefault(require("../../utils/Comparator"));
|
|
8
|
+
class LinkedList {
|
|
9
|
+
constructor(comparatorFunction) {
|
|
10
10
|
this.head = null;
|
|
11
11
|
this.tail = null;
|
|
12
12
|
this.compare = new Comparator_1.default(comparatorFunction);
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
prepend(value) {
|
|
15
15
|
// Make new node to be a head.
|
|
16
16
|
this.head = new LinkedListNode_1.default(value, this.head);
|
|
17
17
|
return this;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
}
|
|
19
|
+
append(value) {
|
|
20
|
+
const newNode = new LinkedListNode_1.default(value);
|
|
21
21
|
// If there is no head yet let's make new node a head.
|
|
22
22
|
if (!this.head) {
|
|
23
23
|
this.head = newNode;
|
|
@@ -28,18 +28,18 @@ var LinkedList = /** @class */ (function () {
|
|
|
28
28
|
this.tail.next = newNode;
|
|
29
29
|
this.tail = newNode;
|
|
30
30
|
return this;
|
|
31
|
-
}
|
|
32
|
-
|
|
31
|
+
}
|
|
32
|
+
delete(value) {
|
|
33
33
|
if (!this.head) {
|
|
34
34
|
return null;
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
let deletedNode = null;
|
|
37
37
|
// If the head must be deleted then make 2nd node to be a head.
|
|
38
38
|
while (this.head && this.compare.equal(this.head.value, value)) {
|
|
39
39
|
deletedNode = this.head;
|
|
40
40
|
this.head = this.head.next;
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
let currentNode = this.head;
|
|
43
43
|
if (currentNode !== null) {
|
|
44
44
|
// If next node must be deleted then make next node to be a next next one.
|
|
45
45
|
while (currentNode.next) {
|
|
@@ -57,14 +57,12 @@ var LinkedList = /** @class */ (function () {
|
|
|
57
57
|
this.tail = currentNode;
|
|
58
58
|
}
|
|
59
59
|
return deletedNode;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (value === void 0) { value = undefined; }
|
|
63
|
-
if (callback === void 0) { callback = undefined; }
|
|
60
|
+
}
|
|
61
|
+
find(value = undefined, callback = undefined) {
|
|
64
62
|
if (!this.head) {
|
|
65
63
|
return null;
|
|
66
64
|
}
|
|
67
|
-
|
|
65
|
+
let currentNode = this.head;
|
|
68
66
|
while (currentNode) {
|
|
69
67
|
// If callback is specified then try to find node by callback.
|
|
70
68
|
if (callback && callback(currentNode.value)) {
|
|
@@ -77,17 +75,17 @@ var LinkedList = /** @class */ (function () {
|
|
|
77
75
|
currentNode = currentNode.next;
|
|
78
76
|
}
|
|
79
77
|
return null;
|
|
80
|
-
}
|
|
81
|
-
|
|
78
|
+
}
|
|
79
|
+
deleteTail() {
|
|
82
80
|
if (this.head === this.tail) {
|
|
83
|
-
|
|
81
|
+
const deletedTail = this.tail;
|
|
84
82
|
this.head = null;
|
|
85
83
|
this.tail = null;
|
|
86
|
-
return
|
|
84
|
+
return deletedTail;
|
|
87
85
|
}
|
|
88
|
-
|
|
86
|
+
const deletedTail = this.tail;
|
|
89
87
|
// Rewind to the last node and delete "next" link for the node before the last one.
|
|
90
|
-
|
|
88
|
+
let currentNode = this.head;
|
|
91
89
|
while (currentNode.next) {
|
|
92
90
|
if (!currentNode.next.next) {
|
|
93
91
|
currentNode.next = null;
|
|
@@ -98,12 +96,12 @@ var LinkedList = /** @class */ (function () {
|
|
|
98
96
|
}
|
|
99
97
|
this.tail = currentNode;
|
|
100
98
|
return deletedTail;
|
|
101
|
-
}
|
|
102
|
-
|
|
99
|
+
}
|
|
100
|
+
deleteHead() {
|
|
103
101
|
if (!this.head) {
|
|
104
102
|
return null;
|
|
105
103
|
}
|
|
106
|
-
|
|
104
|
+
const deletedHead = this.head;
|
|
107
105
|
if (this.head.next) {
|
|
108
106
|
this.head = this.head.next;
|
|
109
107
|
}
|
|
@@ -112,23 +110,20 @@ var LinkedList = /** @class */ (function () {
|
|
|
112
110
|
this.tail = null;
|
|
113
111
|
}
|
|
114
112
|
return deletedHead;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
}
|
|
114
|
+
toArray() {
|
|
115
|
+
const nodes = [];
|
|
116
|
+
let currentNode = this.head;
|
|
119
117
|
while (currentNode) {
|
|
120
118
|
nodes.push(currentNode);
|
|
121
119
|
currentNode = currentNode.next;
|
|
122
120
|
}
|
|
123
121
|
return nodes;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (callback === void 0) { callback = undefined; }
|
|
122
|
+
}
|
|
123
|
+
toString(callback = undefined) {
|
|
127
124
|
return this.toArray()
|
|
128
|
-
.map(
|
|
125
|
+
.map((node) => node.toString(callback))
|
|
129
126
|
.toString();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
}());
|
|
127
|
+
}
|
|
128
|
+
}
|
|
133
129
|
exports.default = LinkedList;
|
|
134
|
-
//# sourceMappingURL=LinkedList.js.map
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (next === void 0) { next = null; }
|
|
3
|
+
class LinkedListNode {
|
|
4
|
+
constructor(value, next = null) {
|
|
6
5
|
this.value = value;
|
|
7
6
|
this.next = next;
|
|
8
7
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return LinkedListNode;
|
|
14
|
-
}());
|
|
8
|
+
toString(callback = undefined) {
|
|
9
|
+
return callback ? callback(this.value) : `${this.value}`;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
15
12
|
exports.default = LinkedListNode;
|
|
16
|
-
//# sourceMappingURL=LinkedListNode.js.map
|
|
@@ -6,12 +6,12 @@ exports.depthFirstSearch = void 0;
|
|
|
6
6
|
* @returns {Callbacks}
|
|
7
7
|
*/
|
|
8
8
|
function initCallbacks(callbacks) {
|
|
9
|
-
|
|
9
|
+
const initiatedCallback = Object.assign({}, callbacks);
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return
|
|
11
|
+
const stubCallback = () => { };
|
|
12
|
+
const allowTraversalCallback = (() => {
|
|
13
|
+
const seen = {};
|
|
14
|
+
return (_previousVertex, _currentVertex, nextVertex) => {
|
|
15
15
|
if (!seen[nextVertex.getKey()]) {
|
|
16
16
|
seen[nextVertex.getKey()] = true;
|
|
17
17
|
return true;
|
|
@@ -34,7 +34,7 @@ function depthFirstSearchRecursive(graph, currentVertex, previousVertex, callbac
|
|
|
34
34
|
if (!callbacks.enterVertex(currentVertex, previousVertex)) {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
graph.getNeighbors(currentVertex).forEach(
|
|
37
|
+
graph.getNeighbors(currentVertex).forEach((nextVertex) => {
|
|
38
38
|
if (callbacks.allowTraversal(previousVertex, currentVertex, nextVertex)) {
|
|
39
39
|
depthFirstSearchRecursive(graph, nextVertex, currentVertex, callbacks);
|
|
40
40
|
}
|
|
@@ -42,8 +42,7 @@ function depthFirstSearchRecursive(graph, currentVertex, previousVertex, callbac
|
|
|
42
42
|
callbacks.leaveVertex(currentVertex, previousVertex);
|
|
43
43
|
}
|
|
44
44
|
function depthFirstSearch(graph, startVertex, callbacks) {
|
|
45
|
-
|
|
45
|
+
const previousVertex = null;
|
|
46
46
|
depthFirstSearchRecursive(graph, startVertex, previousVertex, initCallbacks(callbacks));
|
|
47
47
|
}
|
|
48
48
|
exports.depthFirstSearch = depthFirstSearch;
|
|
49
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
const depth_first_search_1 = require("../depth-first-search");
|
|
4
4
|
/**
|
|
5
5
|
* Detect cycle in directed graph using Depth First Search.
|
|
6
6
|
*
|
|
7
7
|
* @returns the cycle of vertexes, not including the final vertex which is the same as the first.
|
|
8
8
|
*/
|
|
9
9
|
function detectDirectedCycle(graph) {
|
|
10
|
-
|
|
10
|
+
const cycles = [];
|
|
11
11
|
// Will store parents (previous vertices) for all visited nodes.
|
|
12
12
|
// This will be needed in order to specify what path exactly is a cycle.
|
|
13
|
-
|
|
13
|
+
const dfsParentMap = new Map();
|
|
14
14
|
// White set (UNVISITED) contains all the vertices that haven't been visited at all.
|
|
15
|
-
|
|
15
|
+
const whiteSet = new Map();
|
|
16
16
|
// Gray set (VISITING) contains all the vertices that are being visited right now
|
|
17
17
|
// (in current path).
|
|
18
|
-
|
|
18
|
+
const graySet = new Map();
|
|
19
19
|
// Black set (VISITED) contains all the vertices that has been fully visited.
|
|
20
20
|
// Meaning that all children of the vertex has been visited.
|
|
21
|
-
|
|
21
|
+
const blackSet = new Map();
|
|
22
22
|
// If we encounter vertex in gray set it means that we've found a cycle.
|
|
23
23
|
// Because when vertex in gray set it means that its neighbors or its neighbors
|
|
24
24
|
// neighbors are still being explored.
|
|
25
25
|
// Init white set and add all vertices to it.
|
|
26
|
-
graph.getAllVertices().forEach(
|
|
26
|
+
graph.getAllVertices().forEach((vertex) => {
|
|
27
27
|
whiteSet.set(vertex.getKey(), vertex);
|
|
28
28
|
});
|
|
29
29
|
// Describe BFS callbacks.
|
|
30
|
-
|
|
31
|
-
enterVertex:
|
|
30
|
+
const callbacks = {
|
|
31
|
+
enterVertex: (currentVertex, previousVertex) => {
|
|
32
32
|
if (graySet.has(currentVertex.getKey())) {
|
|
33
33
|
// If current vertex already in grey set it means that cycle is detected.
|
|
34
34
|
// Let's detect cycle path.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const cycle = [];
|
|
36
|
+
let currentCycleVertex = currentVertex;
|
|
37
|
+
let previousCycleVertex = previousVertex;
|
|
38
38
|
while (previousCycleVertex.getKey() !== currentVertex.getKey()) {
|
|
39
39
|
cycle.push(currentCycleVertex);
|
|
40
40
|
currentCycleVertex = previousCycleVertex;
|
|
@@ -53,13 +53,13 @@ function detectDirectedCycle(graph) {
|
|
|
53
53
|
return true;
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
|
-
leaveVertex:
|
|
56
|
+
leaveVertex: (currentVertex) => {
|
|
57
57
|
// If all node's children has been visited let's remove it from gray set
|
|
58
58
|
// and move it to the black set meaning that all its neighbors are visited.
|
|
59
59
|
blackSet.set(currentVertex.getKey(), currentVertex);
|
|
60
60
|
graySet.delete(currentVertex.getKey());
|
|
61
61
|
},
|
|
62
|
-
allowTraversal:
|
|
62
|
+
allowTraversal: (_previousVertex, _currentVertex, nextVertex) => {
|
|
63
63
|
// Allow traversal only for the vertices that are not in black set
|
|
64
64
|
// since all black set vertices have been already visited.
|
|
65
65
|
return !blackSet.has(nextVertex.getKey());
|
|
@@ -67,11 +67,10 @@ function detectDirectedCycle(graph) {
|
|
|
67
67
|
};
|
|
68
68
|
// Start exploring vertices.
|
|
69
69
|
while (whiteSet.size > 0) {
|
|
70
|
-
|
|
70
|
+
const startVertex = whiteSet.values().next().value;
|
|
71
71
|
// Do Depth First Search.
|
|
72
72
|
(0, depth_first_search_1.depthFirstSearch)(graph, startVertex, callbacks);
|
|
73
73
|
}
|
|
74
74
|
return cycles;
|
|
75
75
|
}
|
|
76
76
|
exports.default = detectDirectedCycle;
|
|
77
|
-
//# sourceMappingURL=index.js.map
|