diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md
index 26a04ede9..c7a6328d9 100644
--- a/GETTING_STARTED.md
+++ b/GETTING_STARTED.md
@@ -83,5 +83,6 @@ Please read through the [Prerequisites](./README.md#hammer_and_wrench-prerequisi
Then open your browser and login to your [local Neo4j Web UI](http://localhost:7474/browser) with "neo4j" as user and the initial password you've chosen.
👉 See [scripts/examples/analyzeAxonFramework.sh](./scripts/examples/analyzeAxonFramework.sh) as an example script that combines all the above steps for a Java Project.
-👉 See [scripts/examples/analyzeReactRouter.sh](./scripts/examples/analyzeReactRouter.sh) as an example script that combines all the above steps for a Typescript Project.
-👉 See [Code Structure Analysis Pipeline](./.github/workflows/java-code-analysis.yml) on how to do this within a GitHub Actions Workflow.
\ No newline at end of file
+👉 See [scripts/examples/analyzeReactRouter.sh](./scripts/examples/analyzeReactRouter.sh) as an example script that combines all the above steps for a Typescript Project.
+👉 See [scripts/examples/analyzeAntDesign.sh](./scripts/examples/analyzeAntDesign.sh) as an example script that combines all the above steps for a large scale monorepo Typescript Project.
+👉 See [Code Structure Analysis Pipeline](./.github/workflows/java-code-analysis.yml) on how to do this within a GitHub Actions Workflow.
diff --git a/cypher/Exploration/Explore_external_Typescript_dependencies.cypher b/cypher/Exploration/Explore_external_Typescript_dependencies.cypher
new file mode 100644
index 000000000..8924df0be
--- /dev/null
+++ b/cypher/Exploration/Explore_external_Typescript_dependencies.cypher
@@ -0,0 +1,9 @@
+// Explore Typescript nodes with globalFqn property by their label, count and if they came from the node_modules folder
+
+MATCH (typescript:TS)
+WHERE typescript.globalFqn IS NOT NULL
+RETURN labels(file)[0..4] AS nodeType
+ ,(typescript.globalFqn contains '/node_modules/') AS isNodeModule
+ ,count(*) AS numberOfNodes
+ ,collect(DISTINCT typescript.globalFqn)[0..9] AS examples
+ORDER BY nodeType ASC, numberOfNodes DESC
\ No newline at end of file
diff --git a/cypher/External_Dependencies/External_module_usage_overall_for_Typescript.cypher b/cypher/External_Dependencies/External_module_usage_overall_for_Typescript.cypher
new file mode 100644
index 000000000..93c734dcd
--- /dev/null
+++ b/cypher/External_Dependencies/External_module_usage_overall_for_Typescript.cypher
@@ -0,0 +1,34 @@
+// External Typescript module usage overall
+
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
+ WITH count(DISTINCT internalElement.globalFqn) AS allInternalElements
+ ,count(DISTINCT internalModule.globalFqn) AS allModules
+ ,collect(DISTINCT internalElement) AS internalElementList
+UNWIND internalElementList AS internalElement
+ MATCH (internalElement)-[externalDependency:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
+ WHERE externalDeclaration.isExternalImport = true
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement)
+ MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
+ WITH allInternalElements
+ ,allModules
+ ,coalesce(nullIf(externalModule.namespace, '') + '/' + externalModule.name, externalModule.name) AS externalModuleName
+ ,count(DISTINCT internalModule.globalFqn) AS numberOfExternalCallerModules
+ ,count(DISTINCT internalElement.globalFqn) AS numberOfExternalCallerElements
+ ,count(externalDependency) AS numberOfExternalDeclarationCalls
+ ,sum(externalDependency.cardinality) AS numberOfExternalDeclarationCallsWeighted
+ ,collect('<' + internalElement.name
+ + '> of module <'
+ + internalModule.name
+ + '> imports <'
+ + externalDeclaration.name
+ + '> from external module <'
+ + externalModule.name + '>')[0..4] AS exampleStories
+RETURN externalModuleName
+ ,numberOfExternalCallerModules
+ ,numberOfExternalCallerElements
+ ,numberOfExternalDeclarationCalls
+ ,numberOfExternalDeclarationCallsWeighted
+ ,allModules
+ ,allInternalElements
+ ,exampleStories
+ ORDER BY numberOfExternalCallerModules DESC, externalModuleName ASC
\ No newline at end of file
diff --git a/cypher/External_Dependencies/External_module_usage_per_internal_module_aggregated_for_Typescript.cypher b/cypher/External_Dependencies/External_module_usage_per_internal_module_aggregated_for_Typescript.cypher
new file mode 100644
index 000000000..6a26f182f
--- /dev/null
+++ b/cypher/External_Dependencies/External_module_usage_per_internal_module_aggregated_for_Typescript.cypher
@@ -0,0 +1,74 @@
+// External Typescript module usage per interal module aggregated
+
+// Get the overall internal module statistics first
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
+ WITH internalModule.name AS internalModuleName
+ ,internalModule.communityLeidenId AS leidenCommunityId
+ ,count(DISTINCT internalElement.globalFqn) AS internalModuleElementsCount
+ ,collect(DISTINCT internalElement) AS internalElementList
+
+// Get the external dependencies for each internal internalElement
+UNWIND internalElementList AS internalElement
+ MATCH (internalElement)-[:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
+ MATCH (internalModule:Module)-[:EXPORTS]->(internalElement)
+ MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
+ WHERE externalDeclaration.isExternalImport = true
+ WITH internalModuleName
+ ,leidenCommunityId
+ ,internalModuleElementsCount
+ ,internalModule.globalFqn AS fullInternalModuleName
+ ,internalElement.globalFqn AS fullInternalElementName
+ ,coalesce(
+ nullIf(externalModule.namespace, '') + '/' + externalModule.name,
+ externalModule.name) AS externalModuleName
+
+// Group by internalModule and external internalElement
+ WITH internalModuleName
+ ,leidenCommunityId
+ ,internalModuleElementsCount
+ ,externalModuleName
+ ,count(DISTINCT fullInternalModuleName) AS internalModulesCount
+ ,COLLECT(DISTINCT fullInternalModuleName)[0..9] AS internalModulesExamples
+ ,count(DISTINCT fullInternalElementName) AS internalElementsCount
+ ,COLLECT(DISTINCT fullInternalElementName)[0..9] AS internalElementsExamples
+ ,100.0 / internalModuleElementsCount * count(DISTINCT fullInternalElementName) AS internalElementsCallingExternalRate
+
+// Pre order the results by number of packages that use the external package dependency descending
+ORDER BY internalModulesCount DESC, internalModuleName ASC
+
+// Optionally filter out external dependencies that are only used by one internal module
+// WHERE internalModulesCount > 1
+
+// Group by internalModule, aggregate statistics and return the results
+RETURN internalModuleName
+ ,leidenCommunityId
+ ,internalModuleElementsCount
+ ,count(DISTINCT externalModuleName) AS numberOfExternalModules
+
+ // Statistics about the packages and their external package usage count
+ ,min(internalModulesCount) AS minNumberOfInternalModules
+ ,max(internalModulesCount) AS maxNumberOfInternalModules
+ ,percentileCont(internalModulesCount, 0.5) AS medNumberOfInternalModules
+ ,avg(internalModulesCount) AS avgNumberOfInternalModules
+ ,stDev(internalModulesCount) AS stdNumberOfInternalModules
+
+ // Statistics about the types and their external package usage count
+ ,min(internalElementsCount) AS minNumberOfInternalElements
+ ,max(internalElementsCount) AS maxNumberOfInternalElements
+ ,percentileCont(internalElementsCount, 0.5) AS medNumberOfInternalElements
+ ,avg(internalElementsCount) AS avgNumberOfInternalElements
+ ,stDev(internalElementsCount) AS stdNumberOfInternalElements
+
+ // Statistics about the types and their external package usage count percentage
+ ,min(internalElementsCallingExternalRate) AS minNumberOfInternalElementsPercentage
+ ,max(internalElementsCallingExternalRate) AS maxNumberOfInternalElementsPercentage
+ ,percentileCont(internalElementsCallingExternalRate, 0.5) AS medNumberOfInternalElementsPercentage
+ ,avg(internalElementsCallingExternalRate) AS avgNumberOfInternalElementsPercentage
+ ,stDev(internalElementsCallingExternalRate) AS stdNumberOfInternalElementsPercentage
+
+ // Examples of external packages, caller packages and caller types
+ ,collect(externalModuleName)[0..9] AS top10ExternalPackageNamesByUsageDescending
+ ,COLLECT(internalModulesExamples)[0] AS internalModulesExamples
+ ,COLLECT(internalElementsExamples)[0] AS internalElementsExamples
+
+ORDER BY maxNumberOfInternalModules DESC, internalModuleName ASC
\ No newline at end of file
diff --git a/cypher/External_Dependencies/External_module_usage_per_internal_module_distribution_for_Typescript.cypher b/cypher/External_Dependencies/External_module_usage_per_internal_module_distribution_for_Typescript.cypher
new file mode 100644
index 000000000..92da35e56
--- /dev/null
+++ b/cypher/External_Dependencies/External_module_usage_per_internal_module_distribution_for_Typescript.cypher
@@ -0,0 +1,32 @@
+// External Typescript module usage distribution for internal modules
+
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
+ WITH internalModule.name AS internalModuleName
+ ,count(DISTINCT internalElement.globalFqn) AS numberOfAllInternalElements
+ ,collect(DISTINCT internalElement) AS internalElementList
+UNWIND internalElementList AS internalElement
+ MATCH (internalElement)-[:DEPENDS_ON]->(externalElement:ExternalDeclaration)
+ WHERE externalElement.isExternalImport = true
+ MATCH (internalModule:Module)-[:EXPORTS]->(internalElement)
+ MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalElement)
+ WITH internalModuleName
+ ,numberOfAllInternalElements
+ ,internalModule.globalFqn AS fullInternalModuleName
+ ,internalElement.globalFqn AS fullInternalElementName
+ ,coalesce(
+ nullIf(externalModule.namespace, '') + '/' + externalModule.name,
+ externalModule.name) AS externalModuleName
+ WITH internalModuleName
+ ,numberOfAllInternalElements
+ ,count(DISTINCT externalModuleName) AS externalModuleCount
+ ,COLLECT(DISTINCT externalModuleName)[0..9] AS externalModuleExamples
+ ,count(DISTINCT fullInternalElementName) AS internalElementCount
+ ,COLLECT(DISTINCT fullInternalElementName)[0..9] AS internalElementExamples
+RETURN internalModuleName
+ ,numberOfAllInternalElements
+ ,externalModuleCount
+ ,internalElementCount
+ ,100.0 / numberOfAllInternalElements * internalElementCount AS internalElementsCallingExternalRate
+ ,externalModuleExamples
+ ,internalElementExamples
+ORDER BY internalElementCount DESC, internalModuleName ASC
\ No newline at end of file
diff --git a/cypher/External_Dependencies/External_module_usage_per_internal_module_sorted_for_Typescript.cypher b/cypher/External_Dependencies/External_module_usage_per_internal_module_sorted_for_Typescript.cypher
new file mode 100644
index 000000000..10612d19f
--- /dev/null
+++ b/cypher/External_Dependencies/External_module_usage_per_internal_module_sorted_for_Typescript.cypher
@@ -0,0 +1,49 @@
+// External Typescript module usage per internal module sorted by external usage descending
+
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
+ OPTIONAL MATCH (internalElement)-[:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
+ WHERE externalDeclaration.isExternalImport = true
+ OPTIONAL MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
+ WITH internalModule.name AS internalModuleName
+ ,count(DISTINCT internalElement.globalFqn) AS numberOfAllElementsInInternalModule
+ ,count(DISTINCT externalDeclaration.globalFqn) AS numberOfAllExternalDeclarationsUsedInInternalModule
+ ,count(DISTINCT externalModule.globalFqn) AS numberOfAllExternalModulesUsedInInternalModule
+ ,collect(DISTINCT internalElement) AS internalElementList
+UNWIND internalElementList AS internalElement
+ MATCH (internalElement)-[externalDependency:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
+ WHERE externalDeclaration.isExternalImport = true
+ MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
+ WITH numberOfAllElementsInInternalModule
+ ,numberOfAllExternalDeclarationsUsedInInternalModule
+ ,numberOfAllExternalModulesUsedInInternalModule
+ ,100.0 / numberOfAllElementsInInternalModule * numberOfAllExternalDeclarationsUsedInInternalModule AS externalDeclarationRate
+ ,externalDependency
+ ,internalModuleName
+ ,internalElement.globalFqn AS fullInternalElementName
+ ,internalElement.name AS internalElementName
+ ,coalesce(
+ nullIf(externalModule.namespace, '') + '/' + externalModule.name,
+ externalModule.name) AS externalModuleName
+ ,externalDeclaration.name AS externalDeclarationName
+ WITH numberOfAllElementsInInternalModule
+ ,numberOfAllExternalDeclarationsUsedInInternalModule
+ ,numberOfAllExternalModulesUsedInInternalModule
+ ,externalDeclarationRate
+ ,internalModuleName
+ ,externalModuleName
+ ,count(externalDependency) AS numberOfExternalDeclarationCaller
+ ,sum(externalDependency.cardinality) AS numberOfExternalDeclarationCalls
+ ,collect(DISTINCT externalDeclarationName) AS externalDeclarationNames
+RETURN internalModuleName
+ ,externalModuleName
+ ,numberOfExternalDeclarationCaller
+ ,numberOfExternalDeclarationCalls
+ ,numberOfAllElementsInInternalModule
+ ,numberOfAllExternalDeclarationsUsedInInternalModule
+ ,numberOfAllExternalModulesUsedInInternalModule
+ ,externalDeclarationRate
+ ,externalDeclarationNames
+ORDER BY externalDeclarationRate DESC
+ ,internalModuleName ASC
+ ,numberOfExternalDeclarationCaller DESC
+ ,externalModuleName ASC
\ No newline at end of file
diff --git a/cypher/External_Dependencies/External_module_usage_spread_for_Typescript.cypher b/cypher/External_Dependencies/External_module_usage_spread_for_Typescript.cypher
new file mode 100644
index 000000000..27c9c97c7
--- /dev/null
+++ b/cypher/External_Dependencies/External_module_usage_spread_for_Typescript.cypher
@@ -0,0 +1,58 @@
+// External Typescript module usage spread
+
+// Get the overall internal modules statistics first
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
+ WITH count(DISTINCT internalModule.globalFqn) AS internalModulesCountOverall
+ ,count(DISTINCT internalElement.globalFqn) AS internalElementsCountOverall
+ ,collect(DISTINCT internalElement) AS internalElementList
+
+// Get the external declarations for each internal element
+UNWIND internalElementList AS internalElement
+ MATCH (internalElement)-[:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
+ WHERE externalDeclaration.isExternalImport = true
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement)
+ MATCH (externalModule:TS:ExternalModule)-[:EXPORTS]->(externalDeclaration)
+ WITH internalModulesCountOverall
+ ,internalElementsCountOverall
+ ,coalesce(nullIf(externalModule.namespace, '') + '/' + externalModule.name, externalModule.name) AS externalModuleName
+ ,coalesce(nullIf(internalModule.namespace, '') + '/' + internalModule.name, internalModule.name) AS internalModuleName
+
+ // Gathering counts for every internal element and the external module it uses
+ ,count (DISTINCT externalDeclaration.globalFqn) AS externalDeclarationsCount
+ ,COLLECT(DISTINCT externalDeclaration.globalFqn )[0..9] AS externalDeclarationsExamples
+ ,count (DISTINCT internalElement.globalFqn) AS internalElementsCount
+ ,COLLECT(DISTINCT internalElement.globalFqn )[0..9] AS internalElementsExamples
+ ,100.0 / internalModulesCountOverall
+ * count(DISTINCT internalElement.globalFqn) AS internalElementsCallingExternalRate
+
+// Group by external module
+RETURN externalModuleName
+ ,count(DISTINCT internalModuleName) AS numberOfInternalModules
+
+ // Statistics about how many internal modules are using that external module
+ ,sum(externalDeclarationsCount) AS sumNumberOfUsedExternalDeclarations
+ ,min(externalDeclarationsCount) AS minNumberOfUsedExternalDeclarations
+ ,max(externalDeclarationsCount) AS maxNumberOfUsedExternalDeclarations
+ ,percentileCont(externalDeclarationsCount, 0.5) AS medNumberOfUsedExternalDeclarations
+ ,avg(externalDeclarationsCount) AS avgNumberOfUsedExternalDeclarations
+ ,stDev(externalDeclarationsCount) AS stdNumberOfUsedExternalDeclarations
+
+ // Statistics about the internal elements and their external module usage
+ ,sum(internalElementsCount) AS sumNumberOfInternalElements
+ ,min(internalElementsCount) AS minNumberOfInternalElements
+ ,max(internalElementsCount) AS maxNumberOfInternalElements
+ ,percentileCont(internalElementsCount, 0.5) AS medNumberOfInternalElements
+ ,avg(internalElementsCount) AS avgNumberOfInternalElements
+ ,stDev(internalElementsCount) AS stdNumberOfInternalElements
+
+ // Statistics about the types and their external package usage count percentage
+ ,min(internalElementsCallingExternalRate) AS minNumberOfInternalElementsPercentage
+ ,max(internalElementsCallingExternalRate) AS maxNumberOfInternalElementsPercentage
+ ,percentileCont(internalElementsCallingExternalRate, 0.5) AS medNumberOfInternalElementsPercentage
+ ,avg(internalElementsCallingExternalRate) AS avgNumberOfInternalElementsPercentage
+ ,stDev(internalElementsCallingExternalRate) AS stdNumberOfInternalElementsPercentage
+
+ ,collect(DISTINCT internalModuleName)[0..4] AS internalModuleExamples
+
+// Order the results descending by the number of internal modules that use the external module
+ORDER BY numberOfInternalModules DESC, externalModuleName ASC
\ No newline at end of file
diff --git a/cypher/External_Dependencies/External_namespace_usage_overall_for_Typescript.cypher b/cypher/External_Dependencies/External_namespace_usage_overall_for_Typescript.cypher
new file mode 100644
index 000000000..7c54de825
--- /dev/null
+++ b/cypher/External_Dependencies/External_namespace_usage_overall_for_Typescript.cypher
@@ -0,0 +1,34 @@
+// External Typescript namespace usage overall
+
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
+ WITH count(DISTINCT internalElement.globalFqn) AS allInternalElements
+ ,count(DISTINCT internalModule.globalFqn) AS allModules
+ ,collect(DISTINCT internalElement) AS internalElementList
+UNWIND internalElementList AS internalElement
+ MATCH (internalElement)-[externalDependency:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
+ WHERE externalDeclaration.isExternalImport = true
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement)
+ MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
+ WITH allInternalElements
+ ,allModules
+ ,externalModule.namespace AS externalNamespaceName
+ ,count(DISTINCT internalModule.globalFqn) AS numberOfExternalCallerModules
+ ,count(DISTINCT internalElement.globalFqn) AS numberOfExternalCallerElements
+ ,count(externalDependency) AS numberOfExternalDeclarationCalls
+ ,sum(externalDependency.cardinality) AS numberOfExternalDeclarationCallsWeighted
+ ,collect('<' + internalElement.name
+ + '> of module <'
+ + internalModule.name
+ + '> imports <'
+ + externalDeclaration.name
+ + '> from external namespace <'
+ + externalModule.namespace + '>')[0..4] AS exampleStories
+RETURN externalNamespaceName
+ ,numberOfExternalCallerModules
+ ,numberOfExternalCallerElements
+ ,numberOfExternalDeclarationCalls
+ ,numberOfExternalDeclarationCallsWeighted
+ ,allModules
+ ,allInternalElements
+ ,exampleStories
+ ORDER BY numberOfExternalCallerModules DESC, externalNamespaceName ASC
\ No newline at end of file
diff --git a/cypher/External_Dependencies/External_namespace_usage_per_internal_module_sorted_for_Typescript.cypher b/cypher/External_Dependencies/External_namespace_usage_per_internal_module_sorted_for_Typescript.cypher
new file mode 100644
index 000000000..611508653
--- /dev/null
+++ b/cypher/External_Dependencies/External_namespace_usage_per_internal_module_sorted_for_Typescript.cypher
@@ -0,0 +1,47 @@
+// External Typescript module usage per internal module sorted by external usage descending
+
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
+ OPTIONAL MATCH (internalElement)-[:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
+ WHERE externalDeclaration.isExternalImport = true
+ OPTIONAL MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
+ WITH internalModule.name AS internalModuleName
+ ,count(DISTINCT internalElement.globalFqn) AS numberOfAllElementsInInternalModule
+ ,count(DISTINCT externalDeclaration.globalFqn) AS numberOfAllExternalDeclarationsUsedInInternalModule
+ ,count(DISTINCT externalModule.globalFqn) AS numberOfAllExternalModulesUsedInInternalModule
+ ,collect(DISTINCT internalElement) AS internalElementList
+UNWIND internalElementList AS internalElement
+ MATCH (internalElement)-[externalDependency:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
+ WHERE externalDeclaration.isExternalImport = true
+ MATCH (externalModule:ExternalModule)-[:EXPORTS]->(externalDeclaration)
+ WITH numberOfAllElementsInInternalModule
+ ,numberOfAllExternalDeclarationsUsedInInternalModule
+ ,numberOfAllExternalModulesUsedInInternalModule
+ ,100.0 / numberOfAllElementsInInternalModule * numberOfAllExternalDeclarationsUsedInInternalModule AS externalDeclarationRate
+ ,externalDependency
+ ,internalModuleName
+ ,internalElement.globalFqn AS fullInternalElementName
+ ,internalElement.name AS internalElementName
+ ,externalModule.namespace AS externalNamespaceName
+ ,externalDeclaration.name AS externalDeclarationName
+ WITH numberOfAllElementsInInternalModule
+ ,numberOfAllExternalDeclarationsUsedInInternalModule
+ ,numberOfAllExternalModulesUsedInInternalModule
+ ,externalDeclarationRate
+ ,internalModuleName
+ ,externalNamespaceName
+ ,count(externalDependency) AS numberOfExternalDeclarationCaller
+ ,sum(externalDependency.cardinality) AS numberOfExternalDeclarationCalls
+ ,collect(DISTINCT externalDeclarationName) AS externalDeclarationNames
+RETURN internalModuleName
+ ,externalNamespaceName
+ ,numberOfExternalDeclarationCaller
+ ,numberOfExternalDeclarationCalls
+ ,numberOfAllElementsInInternalModule
+ ,numberOfAllExternalDeclarationsUsedInInternalModule
+ ,numberOfAllExternalModulesUsedInInternalModule
+ ,externalDeclarationRate
+ ,externalDeclarationNames
+ORDER BY externalDeclarationRate DESC
+ ,internalModuleName ASC
+ ,numberOfExternalDeclarationCaller DESC
+ ,externalNamespaceName ASC
\ No newline at end of file
diff --git a/cypher/External_Dependencies/External_namespace_usage_spread_for_Typescript.cypher b/cypher/External_Dependencies/External_namespace_usage_spread_for_Typescript.cypher
new file mode 100644
index 000000000..9aa73dbf8
--- /dev/null
+++ b/cypher/External_Dependencies/External_namespace_usage_spread_for_Typescript.cypher
@@ -0,0 +1,58 @@
+// External Typescript namespace usage spread
+
+// Get the overall internal modules statistics first
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement:TS)
+ WITH count(DISTINCT internalModule.globalFqn) AS internalModulesCountOverall
+ ,count(DISTINCT internalElement.globalFqn) AS internalElementsCountOverall
+ ,collect(DISTINCT internalElement) AS internalElementList
+
+// Get the external declarations for each internal element
+UNWIND internalElementList AS internalElement
+ MATCH (internalElement)-[:DEPENDS_ON]->(externalDeclaration:ExternalDeclaration)
+ WHERE externalDeclaration.isExternalImport = true
+ MATCH (internalModule:TS:Module)-[:EXPORTS]->(internalElement)
+ MATCH (externalModule:TS:ExternalModule)-[:EXPORTS]->(externalDeclaration)
+ WITH internalModulesCountOverall
+ ,internalElementsCountOverall
+ ,externalModule.namespace AS externalModuleNamespace
+ ,coalesce(nullIf(internalModule.namespace, '') + '/' + internalModule.name, internalModule.name) AS internalModuleName
+
+ // Gathering counts for every internal element and the external module it uses
+ ,count (DISTINCT externalDeclaration.globalFqn) AS externalDeclarationsCount
+ ,COLLECT(DISTINCT externalDeclaration.globalFqn )[0..9] AS externalDeclarationsExamples
+ ,count (DISTINCT internalElement.globalFqn) AS internalElementsCount
+ ,COLLECT(DISTINCT internalElement.globalFqn )[0..9] AS internalElementsExamples
+ ,100.0 / internalModulesCountOverall
+ * count(DISTINCT internalElement.globalFqn) AS internalElementsCallingExternalRate
+
+// Group by external module namespace
+RETURN externalModuleNamespace
+ ,count(DISTINCT internalModuleName) AS numberOfInternalModules
+
+ // Statistics about how many internal modules are using that external module
+ ,sum(externalDeclarationsCount) AS sumNumberOfUsedExternalDeclarations
+ ,min(externalDeclarationsCount) AS minNumberOfUsedExternalDeclarations
+ ,max(externalDeclarationsCount) AS maxNumberOfUsedExternalDeclarations
+ ,percentileCont(externalDeclarationsCount, 0.5) AS medNumberOfUsedExternalDeclarations
+ ,avg(externalDeclarationsCount) AS avgNumberOfUsedExternalDeclarations
+ ,stDev(externalDeclarationsCount) AS stdNumberOfUsedExternalDeclarations
+
+ // Statistics about the internal elements and their external module usage
+ ,sum(internalElementsCount) AS sumNumberOfInternalElements
+ ,min(internalElementsCount) AS minNumberOfInternalElements
+ ,max(internalElementsCount) AS maxNumberOfInternalElements
+ ,percentileCont(internalElementsCount, 0.5) AS medNumberOfInternalElements
+ ,avg(internalElementsCount) AS avgNumberOfInternalElements
+ ,stDev(internalElementsCount) AS stdNumberOfInternalElements
+
+ // Statistics about the types and their external package usage count percentage
+ ,min(internalElementsCallingExternalRate) AS minNumberOfInternalElementsPercentage
+ ,max(internalElementsCallingExternalRate) AS maxNumberOfInternalElementsPercentage
+ ,percentileCont(internalElementsCallingExternalRate, 0.5) AS medNumberOfInternalElementsPercentage
+ ,avg(internalElementsCallingExternalRate) AS avgNumberOfInternalElementsPercentage
+ ,stDev(internalElementsCallingExternalRate) AS stdNumberOfInternalElementsPercentage
+
+ ,collect(DISTINCT internalModuleName)[0..4] AS internalModuleExamples
+
+// Order the results descending by the number of internal modules that use the external namespace
+ORDER BY numberOfInternalModules DESC, externalModuleNamespace ASC
\ No newline at end of file
diff --git a/cypher/GitLog/Add_RESOLVES_TO_relationships_to_git_files_for_Java.cypher b/cypher/GitLog/Add_RESOLVES_TO_relationships_to_git_files_for_Java.cypher
index ab5bfe087..67a5256cd 100644
--- a/cypher/GitLog/Add_RESOLVES_TO_relationships_to_git_files_for_Java.cypher
+++ b/cypher/GitLog/Add_RESOLVES_TO_relationships_to_git_files_for_Java.cypher
@@ -10,6 +10,5 @@ MATCH (git_file:File&Git)
WHERE git_file.fileName ENDS WITH codeFileName
MERGE (git_file)-[:RESOLVES_TO]->(code_file)
SET git_file.resolved = true
-RETURN labels(code_file)[0..4] AS codeFileLabels
- ,count(DISTINCT codeFileName) AS numberOfCodeFiles
+RETURN count(DISTINCT codeFileName) AS numberOfCodeFiles
,collect(DISTINCT codeFileName + ' <-> ' + git_file.fileName + '\n')[0..4] AS examples
\ No newline at end of file
diff --git a/cypher/GitLog/Add_RESOLVES_TO_relationships_to_git_files_for_Typescript.cypher b/cypher/GitLog/Add_RESOLVES_TO_relationships_to_git_files_for_Typescript.cypher
index 8ff8024bc..d015f5743 100644
--- a/cypher/GitLog/Add_RESOLVES_TO_relationships_to_git_files_for_Typescript.cypher
+++ b/cypher/GitLog/Add_RESOLVES_TO_relationships_to_git_files_for_Typescript.cypher
@@ -10,6 +10,5 @@ MATCH (git_file:File&Git)
WHERE codeFileName ENDS WITH git_file.fileName
MERGE (git_file)-[:RESOLVES_TO]->(code_file)
SET git_file.resolved = true
-RETURN labels(code_file)[0..4] AS codeFileLabels
- ,count(DISTINCT codeFileName) AS numberOfCodeFiles
+RETURN count(DISTINCT codeFileName) AS numberOfCodeFiles
,collect(DISTINCT codeFileName + ' <-> ' + git_file.fileName + '\n')[0..4] AS examples
\ No newline at end of file
diff --git a/cypher/Typescript_Enrichment/Add_module_properties.cypher b/cypher/Typescript_Enrichment/Add_module_properties.cypher
new file mode 100644
index 000000000..9053e5a2e
--- /dev/null
+++ b/cypher/Typescript_Enrichment/Add_module_properties.cypher
@@ -0,0 +1,21 @@
+// Add "namespace", "module" and "name" properties to Typescript nodes that have a globalFqn property
+
+ MATCH (ts:TS)
+ WHERE ts.globalFqn IS NOT NULL
+ WITH ts
+ ,replace(split(ts.globalFqn, '".')[0],'"', '') AS moduleName
+ ,replace(split(ts.globalFqn, '/index')[0],'"', '') AS moduleNameWithoutIndex
+ ,split(ts.globalFqn, '".')[1] AS symbolName
+ ,split(nullif(reverse(split(reverse(ts.globalFqn), '@')[0]), ts.globalFqn), '/')[0] AS namespaceName
+ ,(ts.globalFqn contains '/node_modules/') AS isNodeModule
+ ,((NOT ts.globalFqn STARTS WITH '/') AND size(split(ts.globalFqn, '/')) < 3) AS isUnresolvedImport
+ WITH *
+ ,reverse(split(reverse(moduleNameWithoutIndex), '/')[0]) AS indexedName
+ ,coalesce('@' + nullif(namespaceName, ''), '') AS namespaceNameWithAtPrefixed
+ SET ts.namespace = namespaceNameWithAtPrefixed
+ ,ts.module = moduleName
+ ,ts.name = coalesce(symbolName, indexedName)
+ ,ts.isNodeModule = isNodeModule
+ ,ts.isUnresolvedImport = isUnresolvedImport
+ ,ts.isExternalImport = isNodeModule OR isUnresolvedImport
+RETURN count(*) AS updatedModules
\ No newline at end of file
diff --git a/cypher/Typescript_Enrichment/Add_name_and_module_properties.cypher b/cypher/Typescript_Enrichment/Add_name_and_module_properties.cypher
deleted file mode 100644
index 84eacdd40..000000000
--- a/cypher/Typescript_Enrichment/Add_name_and_module_properties.cypher
+++ /dev/null
@@ -1,13 +0,0 @@
-// Add "name" and "module" properties to Typescript nodes that have a globalFqn property
-
- MATCH (ts:TS)
- WHERE ts.globalFqn IS NOT NULL
- WITH ts
- ,replace(split(ts.globalFqn, '".')[0],'"', '') AS moduleName
- ,replace(split(ts.globalFqn, '/index')[0],'"', '') AS moduleNameWithoutIndex
- ,split(ts.globalFqn, '".')[1] AS symbolName
- WITH *
- ,reverse(split(reverse(moduleNameWithoutIndex), '/')[0]) AS indexedName
- SET ts.module = moduleName
- ,ts.name = coalesce(symbolName, indexedName)
-RETURN count(*) AS updatedModules
\ No newline at end of file
diff --git a/jupyter/ExternalDependenciesTypescript.ipynb b/jupyter/ExternalDependenciesTypescript.ipynb
new file mode 100644
index 000000000..0c79edbdf
--- /dev/null
+++ b/jupyter/ExternalDependenciesTypescript.ipynb
@@ -0,0 +1,1411 @@
+{
+ "cells": [
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "2f0eabc4",
+ "metadata": {},
+ "source": [
+ "# External Dependencies\n",
+ "
\n",
+ "\n",
+ "### References\n",
+ "- [jqassistant](https://jqassistant.org)\n",
+ "- [Neo4j Python Driver](https://neo4j.com/docs/api/python-driver/current)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4191f259",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os\n",
+ "import pandas as pd\n",
+ "import matplotlib.pyplot as plot\n",
+ "from neo4j import GraphDatabase"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1c5dab37",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Please set the environment variable \"NEO4J_INITIAL_PASSWORD\" in your shell \n",
+ "# before starting jupyter notebook to provide the password for the user \"neo4j\". \n",
+ "# It is not recommended to hardcode the password into jupyter notebook for security reasons.\n",
+ "\n",
+ "driver = GraphDatabase.driver(uri=\"bolt://localhost:7687\", auth=(\"neo4j\", os.environ.get(\"NEO4J_INITIAL_PASSWORD\")))\n",
+ "driver.verify_connectivity()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c1db254b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_cypher_query_from_file(filename):\n",
+ " with open(filename) as file:\n",
+ " return ' '.join(file.readlines())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "59310f6f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def query_cypher_to_data_frame(filename):\n",
+ " records, summary, keys = driver.execute_query(get_cypher_query_from_file(filename))\n",
+ " return pd.DataFrame([r.values() for r in records], columns=keys)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "da9e8edb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#The following cell uses the build-in %html \"magic\" to override the CSS style for tables to a much smaller size.\n",
+ "#This is especially needed for PDF export of tables with multiple columns."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9deaabce",
+ "metadata": {
+ "tags": [
+ "table-css"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "%%html\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c2496caf",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Main Colormap\n",
+ "main_color_map = 'nipy_spectral'"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "6705e06a",
+ "metadata": {},
+ "source": [
+ "## External Typescript Module Usage\n",
+ "\n",
+ "### External Module\n",
+ "\n",
+ "An external Typescript module is marked with the label `ExternalModule` and the declarations it provides with `ExternalDeclaration`. In practice, the distinction between internal and external isn't always that clear. When there is a problem following the project configuration like discussed in [Missing Interfaces and other elements in the Graph](https://github.com/jqassistant-plugin/jqassistant-typescript-plugin/issues/35), some internal dependencies might be imported as external ones. \n",
+ "\n",
+ "To have a second indicator, the property `isNodeModule` is written with [Add_module_properties.cypher](./../cypher/Typescript_Enrichment/Add_module_properties.cypher) in [prepareAnalysis.sh](./../scripts/prepareAnalysis.sh). For most package managers this should then be sufficient. As of now (June 2024), it might not work with [Yarn Plug'n'Play](https://yarnpkg.com/features/pnp)."
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "334167e4",
+ "metadata": {},
+ "source": [
+ "### Table 1 - Top 20 most used external packages overall\n",
+ "\n",
+ "This table shows the external packages that are used by the most different internal types overall.\n",
+ "Additionally, it shows which types of the external modules are actually used. External annotations are also listed.\n",
+ "\n",
+ "Only the top 20 entries are shown. The whole table can be found in the following CSV report:\n",
+ "`External_module_usage_overall_for_Typescript`\n",
+ "\n",
+ "**Columns:**\n",
+ "- *externalModuleName* is the name of the external module prepended by its namespace if given. Example: \"@types/react\"\n",
+ "- *numberOfExternalCallerModules* is the number of modules that use that external module\n",
+ "- *numberOfExternalCallerElements* is the number of elements (functions, classes,...) that use that external module\n",
+ "- *numberOfExternalDeclarationCalls* is how often the external declarations of that external module are imported\n",
+ "- *numberOfExternalDeclarationCallsWeighted* is how often the external declarations of that external module are actually used\n",
+ "- *allModules* contains the total count of all analyzed internal modules\n",
+ "- *allInternalElements* contains the total count of all analyzed exported internal elements (function, classes,...)\n",
+ "- *exampleStories* contains a list of sentences that contain concrete examples (for explanation and debugging)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ff524ac7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_module_usage=query_cypher_to_data_frame(\"../cypher/External_Dependencies/External_module_usage_overall_for_Typescript.cypher\")\n",
+ "\n",
+ "# Select columns and only show the first 20 entries (head)\n",
+ "external_module_usage.head(20)"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "1143afcb",
+ "metadata": {},
+ "source": [
+ "#### Table 1 Chart 1 - Most called external modules in % by internal elements\n",
+ "\n",
+ "External modules that are used less than 0.7% are grouped into \"others\" to get a cleaner chart\n",
+ "containing the most significant external modules and how ofter they are called by internal elements in percent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44a11aec",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def group_to_others_below_threshold(data_frame : pd.DataFrame, value_column : str, name_column: str, threshold: float) -> pd.DataFrame: \n",
+ " \"\"\"Adds a new percentage column for the value column and \n",
+ " groups all values below the given threshold to \"others\" in the name column.\n",
+ "\n",
+ " Parameters:\n",
+ " - data_frame (pd.DataFrame): Input pandas DataFrame\n",
+ " - value_column (str): Name of the column that contains the numeric value\n",
+ " - name_column (str): Name of the column that contains the group name that will be replaced by \"others\" for small values\n",
+ " - threshold (float): Threshold in % that is used to group values below it into the \"others\" group\n",
+ "\n",
+ " Returns:\n",
+ " int:Returning value\n",
+ "\n",
+ " \"\"\"\n",
+ " result_data_frame = data_frame.copy();\n",
+ "\n",
+ " percent_column_name = value_column + 'Percent';\n",
+ "\n",
+ " # Add column with the name given in \"percent_column_name\" with the percentage of the value column.\n",
+ " result_data_frame[percent_column_name] = result_data_frame[value_column] / result_data_frame[value_column].sum() * 100.0;\n",
+ "\n",
+ " # Change the external module name to \"others\" if it is called less than the specified threshold\n",
+ " result_data_frame.loc[result_data_frame[percent_column_name] < threshold, name_column] = 'others';\n",
+ "\n",
+ " # Group external module name (foremost the new \"others\" entries) and sum their percentage\n",
+ " result_data_frame = result_data_frame.groupby(name_column)[percent_column_name].sum();\n",
+ "\n",
+ " # Sort by values descending\n",
+ " return result_data_frame.sort_values(ascending=False);"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "99ef3fad",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_module_by_internal_element_usage_significant = group_to_others_below_threshold(\n",
+ " data_frame=external_module_usage,\n",
+ " value_column='numberOfExternalCallerElements',\n",
+ " name_column='externalModuleName',\n",
+ " threshold= 0.7\n",
+ ");"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "688b6d56",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if external_module_by_internal_element_usage_significant.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ "\n",
+ " axis = external_module_by_internal_element_usage_significant.plot(\n",
+ " kind='pie',\n",
+ " title='Top external module usage [%] by internal elements',\n",
+ " legend=True,\n",
+ " labeldistance=None,\n",
+ " autopct='%1.2f%%',\n",
+ " textprops={'fontsize': 5},\n",
+ " pctdistance=1.2,\n",
+ " cmap=main_color_map\n",
+ " )\n",
+ " axis.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "84c123dc",
+ "metadata": {},
+ "source": [
+ "#### Table 1 Chart 2 - Most called external modules in % by internal modules\n",
+ "\n",
+ "External modules that are used less than 0.7% are grouped into \"others\" to get a cleaner chart\n",
+ "containing the most significant external modules and how ofter they are called by internal modules in percent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c10499a5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_module_used_by_internal_modules_significant = group_to_others_below_threshold(\n",
+ " data_frame=external_module_usage,\n",
+ " value_column='numberOfExternalCallerModules',\n",
+ " name_column='externalModuleName',\n",
+ " threshold= 0.7\n",
+ ");"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c165f403",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if external_module_used_by_internal_modules_significant.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ "\n",
+ " axis = external_module_used_by_internal_modules_significant.plot(\n",
+ " kind='pie',\n",
+ " title='Top external module usage [%] by internal modules',\n",
+ " legend=True,\n",
+ " labeldistance=None,\n",
+ " autopct='%1.2f%%',\n",
+ " textprops={'fontsize': 5},\n",
+ " pctdistance=1.2,\n",
+ " cmap=main_color_map\n",
+ " )\n",
+ " axis.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cb92e603",
+ "metadata": {},
+ "source": [
+ "### Table 2 - Top 20 most used external namespaces\n",
+ "\n",
+ "This table shows external namespaces that are used by the most different internal elements (functions, classes,...) overall. \n",
+ "\n",
+ "Additionally, it shows how many of the declarations of the external namespace are actually used.\n",
+ "\n",
+ "Only the top 20 entries are shown. The whole table can be found in the following CSV report:\n",
+ "`External_namespace_usage_overall_for_Typescript`\n",
+ "\n",
+ "**Columns:**\n",
+ "- *externalNamespaceName* is the name of the external namespace (empty if none). Example: \"@types\". All other columns are aggregated/grouped by it.\n",
+ "- *numberOfExternalCallerModules* is the number of modules that use that external module\n",
+ "- *numberOfExternalCallerElements* is the number of elements (functions, classes,...) that use that external module\n",
+ "- *numberOfExternalDeclarationCalls* is how often the external declarations of that external module are imported\n",
+ "- *numberOfExternalDeclarationCallsWeighted* is how often the external declarations of that external module are actually used\n",
+ "- *allModules* contains the total count of all analyzed internal modules\n",
+ "- *allInternalElements* contains the total count of all analyzed exported internal elements (function, classes,...)\n",
+ "- *exampleStories* contains a list of sentences that contain concrete examples (for explanation and debugging)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4dc5e771",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_namespace_usage=query_cypher_to_data_frame(\"../cypher/External_Dependencies/External_namespace_usage_overall_for_Typescript.cypher\")\n",
+ "external_namespace_usage.head(20)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "279932a6",
+ "metadata": {},
+ "source": [
+ "#### Table 2 Chart 1 - Most called external namespaces in % by internal element\n",
+ "\n",
+ "External namespaces that are used less than 0.7% are grouped into \"others\" to get a cleaner chart\n",
+ "containing the most significant external namespaces and how ofter they are called by internal elements in percent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3d36043f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_namespace_use_by_internal_elements_significantly = group_to_others_below_threshold(\n",
+ " data_frame=external_namespace_usage,\n",
+ " value_column='numberOfExternalCallerElements',\n",
+ " name_column='externalNamespaceName',\n",
+ " threshold= 0.7\n",
+ ");\n",
+ "\n",
+ "if external_namespace_use_by_internal_elements_significantly.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ "\n",
+ " axis = external_namespace_use_by_internal_elements_significantly.plot(\n",
+ " kind='pie',\n",
+ " title='Top external namespace usage [%] by internal elements',\n",
+ " legend=True,\n",
+ " labeldistance=None,\n",
+ " autopct='%1.2f%%',\n",
+ " textprops={'fontsize': 5},\n",
+ " pctdistance=1.2,\n",
+ " cmap=main_color_map\n",
+ " )\n",
+ " axis.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "43c3e1a3",
+ "metadata": {},
+ "source": [
+ "#### Table 2 Chart 2 - Most called external namespaces in % by internal modules\n",
+ "\n",
+ "External namespaces that are used less than 0.7% are grouped into \"others\" to get a cleaner chart\n",
+ "containing the most significant external namespaces and how ofter they are called by internal modules in percent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7f05314f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_namespace_used_by_internal_modules_significantly = group_to_others_below_threshold(\n",
+ " data_frame=external_namespace_usage,\n",
+ " value_column='numberOfExternalCallerModules',\n",
+ " name_column='externalNamespaceName',\n",
+ " threshold= 0.7\n",
+ ");\n",
+ "\n",
+ "if external_namespace_used_by_internal_modules_significantly.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ " axis = external_namespace_used_by_internal_modules_significantly.plot(\n",
+ " kind='pie',\n",
+ " title='Top external namespace usage [%] by internal modules',\n",
+ " legend=True,\n",
+ " labeldistance=None,\n",
+ " autopct='%1.2f%%',\n",
+ " textprops={'fontsize': 5},\n",
+ " pctdistance=1.2,\n",
+ " cmap=main_color_map\n",
+ " )\n",
+ " axis.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2fb30664",
+ "metadata": {},
+ "source": [
+ "### Table 3 - Top 20 most widely spread external modules\n",
+ "\n",
+ "The following tables shows external modules that are used by many different internal modules with the highest number of artifacts first.\n",
+ "\n",
+ "Statistics like minimum, maximum, average, median and standard deviation are provided for the number of internally exported elements (function, class, ...) and the external declarations they use for every external module. \n",
+ "\n",
+ "The intuition behind that is to find external modules and the external declarations they provide that are used in a widely spread manner. This can help to distinguish widely used libraries and frameworks from external modules that are used for specific tasks. It can also be used to find external modules that are used sparsely regarding internal modules but where many different external declarations are used. \n",
+ "\n",
+ "Refactoring with [Hexagonal architecture](https://alistair.cockburn.us/hexagonal-architecture) in mind can be considered for non-framework external modules that are used for very specific tasks and that are used in many different internal locations. This makes the internal code more robust against changes of these external modules or it is easier to update and migrate to newer versions of them. \n",
+ "\n",
+ "External modules that are only used in very few internal locations overall might be considered for removal if they are easy to replace with a similar library that is already used more often. Or they might also simply be replaced by very few lines of code. Replacing libraries with own code isn't recommended when you need to write a lot of code or for external modules that provide security relevant implementations (encryption, sanitizers, ...), because they will be tracked and maintained globally and security updates need to be adopted fast.\n",
+ "\n",
+ "Only the top 20 entries are shown. The whole table can be found in the following CSV report:\n",
+ "`External_module_usage_spread_for_Typescript`\n",
+ "\n",
+ "**Columns:**\n",
+ "- *externalModuleName* is the name of the external package prepended by its namespace if given. Example: \"@types/react\"\n",
+ "external package.\n",
+ "- *numberOfInternalModules* is the number of internal modules that are using that external module\n",
+ "- *\\[min,max,med,avg,std\\]NumberOfUsedExternalDeclarations* provide statistics for all internal modules and how their usage of the declarations provided by the external module are distributed. This provides an indicator on how strong the coupling to the external module is. For example, if many (high sum) elements provided by that external module are used constantly (low std), a higher coupling can be presumed. If there is only one (sum) element in use, this could be an indicator for an external module that could get replaced or that there is just one central entry point for it.\n",
+ "- *\\[min/max/med/avg/std\\]NumberOfInternalElements* provide statistics for all internal modules and how their usage of the external module is distributed across their internal elements. This provides an indicator on how widely an external module is spread across internal elements and if there are great differences between internal modules (high standard deviation) or not.\n",
+ "- *\\[min/max/med/avg/std\\]NumberOfInternalElementsPercentage* is similar to [min/max/med/avg/std]NumberOfUsedExternalDeclarations but provides the value in percent in relation to the total number of internal elements per internal module.\n",
+ "- *internalModuleExamples* some examples of included internal modules for debugging"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ad1a04c4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Query the graph database to provide the \n",
+ "# most widely spread external dependencies for the tables/charts below.\n",
+ "external_module_usage_spread=query_cypher_to_data_frame(\"../cypher/External_Dependencies/External_module_usage_spread_for_Typescript.cypher\")\n",
+ "external_module_usage_spread.head(10)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6ed201cc",
+ "metadata": {},
+ "source": [
+ "### Table 3a - Top 20 most widely spread external packages - number of internal modules\n",
+ "\n",
+ "This table shows the top 20 most widely spread external packages focussing on the spread across the number of internal modules."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c5fa9f9e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_package_usage_spread_packages=external_module_usage_spread[['externalModuleName', 'numberOfInternalModules', 'minNumberOfInternalElements', 'maxNumberOfInternalElements', 'medNumberOfInternalElements', 'avgNumberOfInternalElements', 'stdNumberOfInternalElements']]\n",
+ "external_package_usage_spread_packages.head(20)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "27c5b75f",
+ "metadata": {},
+ "source": [
+ "### Table 3b - Top 20 most widely spread external packages - percentage of internal modules\n",
+ "\n",
+ "This table shows the top 20 most widely spread external packages focussing on the spread across the percentage of internal modules."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c4d4273e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_package_usage_spread_packages_percentage=external_module_usage_spread[['externalModuleName', 'numberOfInternalModules', 'minNumberOfInternalElementsPercentage', 'maxNumberOfInternalElementsPercentage', 'medNumberOfInternalElementsPercentage', 'avgNumberOfInternalElementsPercentage', 'stdNumberOfInternalElementsPercentage']]\n",
+ "external_package_usage_spread_packages_percentage.head(20)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d7638e05",
+ "metadata": {},
+ "source": [
+ "### Table 3c - Top 20 most widely spread external packages - number of internal elements\n",
+ "\n",
+ "This table shows the top 20 most widely spread external packages focussing on the spread across the number of internal elements."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1f5af910",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_package_usage_spread_types=external_module_usage_spread[['externalModuleName', 'numberOfInternalModules', 'minNumberOfInternalElements', 'maxNumberOfInternalElements', 'medNumberOfInternalElements', 'avgNumberOfInternalElements', 'stdNumberOfInternalElements']]\n",
+ "external_package_usage_spread_types.head(20)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "07427cd5",
+ "metadata": {},
+ "source": [
+ "### Table 3d - Top 20 most widely spread external packages - percentage of internal elements\n",
+ "\n",
+ "This table shows the top 20 most widely spread external packages focussing on the spread across the percentage of internal elements."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "50712f90",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_package_usage_spread_types_percentage=external_module_usage_spread[['externalModuleName', 'numberOfInternalModules', 'minNumberOfInternalElementsPercentage', 'maxNumberOfInternalElementsPercentage', 'medNumberOfInternalElementsPercentage', 'avgNumberOfInternalElementsPercentage', 'stdNumberOfInternalElementsPercentage']]\n",
+ "external_package_usage_spread_types_percentage.head(20)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b210eea0",
+ "metadata": {},
+ "source": [
+ "#### Table 3 Chart 1 - Most widely spread external packages in % by types\n",
+ "\n",
+ "External packages that are used less than 0.5% are grouped into the name \"others\" to get a cleaner chart with the most significant external packages."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f41d04c9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_module_by_internal_element_usage_spread_significant = group_to_others_below_threshold(\n",
+ " data_frame=external_module_usage_spread,\n",
+ " value_column='sumNumberOfInternalElements',\n",
+ " name_column='externalModuleName',\n",
+ " threshold= 0.5\n",
+ ");\n",
+ "\n",
+ "if external_module_by_internal_element_usage_spread_significant.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ " axis = external_module_by_internal_element_usage_spread_significant.plot(\n",
+ " kind='pie',\n",
+ " title='Top external module usage spread [%] by internal elements',\n",
+ " legend=True,\n",
+ " labeldistance=None,\n",
+ " autopct='%1.2f%%',\n",
+ " textprops={'fontsize': 5},\n",
+ " pctdistance=1.2,\n",
+ " cmap=main_color_map\n",
+ " )\n",
+ " axis.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c48740e3",
+ "metadata": {},
+ "source": [
+ "#### Table 3 Chart 2 - Most widely spread external modules in % by internal modules\n",
+ "\n",
+ "External modules that are used less than 0.5% are grouped into \"others\" to get a cleaner chart containing the most significant external modules."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8bb7b0d9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_modules_used_by_internal_modules_spread_significant = group_to_others_below_threshold(\n",
+ " data_frame=external_module_usage_spread,\n",
+ " value_column='numberOfInternalModules',\n",
+ " name_column='externalModuleName',\n",
+ " threshold= 0.5\n",
+ ");\n",
+ "\n",
+ "if external_modules_used_by_internal_modules_spread_significant.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ " axis = external_modules_used_by_internal_modules_spread_significant.plot(\n",
+ " kind='pie',\n",
+ " title='Top external module usage spread [%] by internal modules',\n",
+ " legend=True,\n",
+ " labeldistance=None,\n",
+ " autopct='%1.2f%%',\n",
+ " textprops={'fontsize': 5},\n",
+ " pctdistance=1.2,\n",
+ " cmap=main_color_map\n",
+ " )\n",
+ " axis.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2d6762ea",
+ "metadata": {},
+ "source": [
+ "### Table 4 - Top 20 most widely spread external namespaces\n",
+ "\n",
+ "This table shows external namespaces that are used by different internal modules with the most used first. \n",
+ "\n",
+ "Statistics like minimum, maximum, average, median and standard deviation are provided for the number of internally exported elements (function, class, ...) and the external declarations they use for every external namespace. \n",
+ "\n",
+ "The intuition behind that is to find external namespaces that are used in a widely spread manner. This can help to distinguish widely used libraries and frameworks from external modules that are used for specific tasks. It can also be used to find external modules that are used sparsely regarding internal modules but where many different external declarations are used. \n",
+ "\n",
+ "Refactoring with a [Hexagonal architecture](https://alistair.cockburn.us/hexagonal-architecture) in mind can be considered for non-framework external namespaces that are used for very specific tasks and that are used in many different internal locations. This makes the internal code more robust against changes of these external modules or it is easier to update and migrate to newer versions of them. \n",
+ "\n",
+ "External namespaces that are only used in very few internal locations overall might be considered for removal if they are easy to replace with a similar library that is already used more often. Or they might also simply be replaced by very few lines of code. Replacing libraries with own code isn't recommended when you need to write a lot of code or for external modules that provide security relevant implementations (encryption, sanitizers, ...), because they will be tracked and maintained globally and security updates need to be adopted fast.\n",
+ "\n",
+ "Only the top 20 entries are shown. The whole table can be found in the following CSV report:\n",
+ "`External_namespace_usage_spread_for_Typescript`\n",
+ "\n",
+ "**Columns:**\n",
+ "- *externalModuleNamespace* identifies the external namespace for at least on external module in use. All other columns contain aggregated data for it.\n",
+ "- *numberOfInternalModules* is the number of internal modules that are using that external module\n",
+ "- *\\[min,max,med,avg,std\\]NumberOfUsedExternalDeclarations* provide statistics for all internal modules and how their usage of the declarations provided by the external module are distributed. This provides an indicator on how strong the coupling to the external module is. For example, if many (high sum) elements provided by that external module are used constantly (low std), a higher coupling can be presumed. If there is only one (sum) element in use, this could be an indicator for an external module that could get replaced or that there is just one central entry point for it.\n",
+ "- *\\[min/max/med/avg/std\\]NumberOfInternalElements* provide statistics for all internal modules and how their usage of the external module is distributed across their internal elements. This provides an indicator on how widely an external module is spread across internal elements and if there are great differences between internal modules (high standard deviation) or not.\n",
+ "- *\\[min/max/med/avg/std\\]NumberOfInternalElementsPercentage* is similar to [min/max/med/avg/std]NumberOfUsedExternalDeclarations but provides the value in percent in relation to the total number of internal elements per internal module.\n",
+ "- *internalModuleExamples* some examples of included internal modules for debugging"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f6cde5e6",
+ "metadata": {},
+ "source": [
+ "### Table 4 - Top 20 most widely spread external namespaces\n",
+ "\n",
+ "This table shows external namespaces that are used by different internal modules with the most used first. \n",
+ "\n",
+ "Statistics like minimum, maximum, average, median and standard deviation are provided for the number of internally exported elements (function, class, ...) and the external declarations they use for every external namespace. \n",
+ "\n",
+ "The intuition behind that is to find external namespaces that are used in a widely spread manner. This can help to distinguish widely used libraries and frameworks from external modules that are used for specific tasks. It can also be used to find external modules that are used sparsely regarding internal modules but where many different external declarations are used. \n",
+ "\n",
+ "Refactoring with a [Hexagonal architecture](https://alistair.cockburn.us/hexagonal-architecture) in mind can be considered for non-framework external namespaces that are used for very specific tasks and that are used in many different internal locations. This makes the internal code more robust against changes of these external modules or it is easier to update and migrate to newer versions of them. \n",
+ "\n",
+ "External namespaces that are only used in very few internal locations overall might be considered for removal if they are easy to replace with a similar library that is already used more often. Or they might also simply be replaced by very few lines of code. Replacing libraries with own code isn't recommended when you need to write a lot of code or for external modules that provide security relevant implementations (encryption, sanitizers, ...), because they will be tracked and maintained globally and security updates need to be adopted fast.\n",
+ "\n",
+ "Only the top 20 entries are shown. The whole table can be found in the following CSV report:\n",
+ "`External_namespace_usage_spread_for_Typescript`\n",
+ "\n",
+ "**Columns:**\n",
+ "- *externalModuleNamespace* identifies the external namespace for at least on external module in use. All other columns contain aggregated data for it.\n",
+ "- *numberOfInternalModules* is the number of internal modules that are using that external module\n",
+ "- *\\[min,max,med,avg,std\\]NumberOfUsedExternalDeclarations* provide statistics for all internal modules and how their usage of the declarations provided by the external module are distributed. This provides an indicator on how strong the coupling to the external module is. For example, if many (high sum) elements provided by that external module are used constantly (low std), a higher coupling can be presumed. If there is only one (sum) element in use, this could be an indicator for an external module that could get replaced or that there is just one central entry point for it.\n",
+ "- *\\[min/max/med/avg/std\\]NumberOfInternalElements* provide statistics for all internal modules and how their usage of the external module is distributed across their internal elements. This provides an indicator on how widely an external module is spread across internal elements and if there are great differences between internal modules (high standard deviation) or not.\n",
+ "- *\\[min/max/med/avg/std\\]NumberOfInternalElementsPercentage* is similar to [min/max/med/avg/std]NumberOfUsedExternalDeclarations but provides the value in percent in relation to the total number of internal elements per internal module.\n",
+ "- *internalModuleExamples* some examples of included internal modules for debugging"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "afd344dc",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_namespace_usage_spread=query_cypher_to_data_frame(\"../cypher/External_Dependencies/External_namespace_usage_spread_for_Typescript.cypher\")\n",
+ "external_namespace_usage_spread.head(20)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "04840973",
+ "metadata": {},
+ "source": [
+ "#### Table 4 Chart 1 - Most widely spread external namespaces in % by internal element\n",
+ "\n",
+ "External namespaces that are used less than 0.5% are grouped into \"others\" to get a cleaner chart\n",
+ "containing the most significant external namespaces and how ofter they are called in percent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c5e7c339",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_namespace_usage_significant = group_to_others_below_threshold(\n",
+ " data_frame=external_namespace_usage_spread,\n",
+ " value_column='sumNumberOfInternalElements',\n",
+ " name_column='externalModuleNamespace',\n",
+ " threshold= 0.5\n",
+ ");\n",
+ "\n",
+ "if external_namespace_usage_significant.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ "\n",
+ " axis = external_namespace_usage_significant.plot(\n",
+ " kind='pie',\n",
+ " title='Top external namespace usage spread [%] by internal elements',\n",
+ " legend=True,\n",
+ " labeldistance=None,\n",
+ " autopct='%1.2f%%',\n",
+ " textprops={'fontsize': 5},\n",
+ " pctdistance=1.2,\n",
+ " cmap=main_color_map\n",
+ " )\n",
+ " axis.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fb678b02",
+ "metadata": {},
+ "source": [
+ "#### Table 4 Chart 2 - Most widely spread external namespace in % by internal modules\n",
+ "\n",
+ "External namespaces that are used less than 0.5% are grouped into \"others\" to get a cleaner chart\n",
+ "containing the most significant external namespaces and how ofter they are called in percent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d74f8422",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_namespace_internal_module_usage_spread_significant = group_to_others_below_threshold(\n",
+ " data_frame=external_namespace_usage_spread,\n",
+ " value_column='numberOfInternalModules',\n",
+ " name_column='externalModuleNamespace',\n",
+ " threshold= 0.5\n",
+ ");\n",
+ "\n",
+ "if external_namespace_internal_module_usage_spread_significant.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ "\n",
+ " axis = external_namespace_internal_module_usage_spread_significant.plot(\n",
+ " kind='pie',\n",
+ " title='Top external namespace usage spread [%] by internal modules',\n",
+ " legend=True,\n",
+ " labeldistance=None,\n",
+ " autopct='%1.2f%%',\n",
+ " textprops={'fontsize': 5},\n",
+ " pctdistance=1.2,\n",
+ " cmap=main_color_map\n",
+ " )\n",
+ " axis.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14e4da22",
+ "metadata": {},
+ "source": [
+ "#### Table 4 Chart 3 - External namespaces with the most used declarations in %\n",
+ "\n",
+ "External namespaces that are used less than 0.5% are grouped into \"others\" to get a cleaner chart\n",
+ "containing the most significant external namespaces and how ofter they are called in percent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "409db3b3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_namespace_declaration_usage_significant = group_to_others_below_threshold(\n",
+ " data_frame=external_namespace_usage_spread,\n",
+ " value_column='sumNumberOfUsedExternalDeclarations',\n",
+ " name_column='externalModuleNamespace',\n",
+ " threshold= 0.5\n",
+ ");\n",
+ "\n",
+ "if external_namespace_declaration_usage_significant.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ "\n",
+ " axis = external_namespace_declaration_usage_significant.plot(\n",
+ " kind='pie',\n",
+ " title='Top external namespace declaration usage [%]',\n",
+ " legend=True,\n",
+ " labeldistance=None,\n",
+ " autopct='%1.2f%%',\n",
+ " textprops={'fontsize': 5},\n",
+ " pctdistance=1.2,\n",
+ " cmap=main_color_map\n",
+ " )\n",
+ " axis.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "29ec2211",
+ "metadata": {},
+ "source": [
+ "### Table 5 - Top 20 least used external modules overall\n",
+ "\n",
+ "This table identifies external modules that aren't used very often. This could help to find libraries that aren't actually needed or maybe easily replaceable. Some of them might be used sparsely on purpose for example as an adapter to an external library that is actually important. Thus, decisions need to be made on a case-by-case basis.\n",
+ "\n",
+ "Only the last 20 entries are shown. The whole table can be found in the following CSV report:\n",
+ "`External_module_usage_overall_for_Typescript`\n",
+ "\n",
+ "**Columns:**\n",
+ "- *externalModuleName* identifies the external package as described above\n",
+ "- *numberOfExternalDeclarationCalls* includes every invocation or reference to the declarations in the external module"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "03641b8b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Sort by number of external type calls\n",
+ "external_package_least_used=external_module_usage.sort_values(by='numberOfExternalDeclarationCalls', ascending=True)\n",
+ "\n",
+ "# Reset index\n",
+ "external_package_least_used = external_package_least_used.reset_index(drop=True)\n",
+ "\n",
+ "# Select columns and only show the first 10 entries (head)\n",
+ "external_package_least_used[['externalModuleName','numberOfExternalDeclarationCalls']].head(20)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0bd11586",
+ "metadata": {},
+ "source": [
+ "### Table 6 - External usage per internal module sorted by highest external element usage rate descending\n",
+ "\n",
+ "The following table shows the most used external packages separately for each artifact including external annotations. The results are sorted by the artifacts with the highest external type usage rate descending. \n",
+ "\n",
+ "The intention of this table is to find artifacts that use a lot of external dependencies in relation to their size and get all the external packages and their usage.\n",
+ "\n",
+ "Only the first 40 entries are shown. The whole table can be found in the following CSV report:\n",
+ "`External_module_usage_per_internal_module_sorted_for_Typescript`\n",
+ "\n",
+ "**Columns:**\n",
+ "- *internalModuleName* is the internal module that uses the external one. Both are used here as a group for a more detailed analysis.\n",
+ "- *externalModuleName* is the external module prepended by its namespace if given. Example: \"@types/react\"\n",
+ "- *numberOfExternalDeclarationCaller* is the count of distinct internal elements in the internal module that call the external module\n",
+ "- *numberOfExternalDeclarationCalls* is the count of how often the external module is called within the internal module\n",
+ "- *numberOfAllElementsInInternalModule* is the total count of all exported elements of the internal module\n",
+ "- *numberOfAllExternalDeclarationsUsedInInternalModule* is the total count of all distinct external declarations used in the internal module\n",
+ "- *numberOfAllExternalModulesUsedInInternalModule* is the total count of all distinct external modules used in the internal module\n",
+ "- *externalDeclarationRate* is the numberOfAllExternalDeclarationsUsedInInternalModule / numberOfAllElementsInInternalModule * 100 of the internal module for all external modules\n",
+ "- *externalDeclarationNames* contains a list of actually used external declarations"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f6be4357",
+ "metadata": {},
+ "source": [
+ "#### Table 6a - External module usage per internal module sorted by highest external element usage rate descending"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f8459ede",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_modules_used_by_internal_modules = query_cypher_to_data_frame(\"../cypher/External_Dependencies/External_module_usage_per_internal_module_sorted_for_Typescript.cypher\")\n",
+ "external_modules_used_by_internal_modules.head(40)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2635122d",
+ "metadata": {},
+ "source": [
+ "#### Table 6b - External namespace usage per internal module sorted by highest external element usage rate descending"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10f373b1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_namespaces_used_by_internal_modules = query_cypher_to_data_frame(\"../cypher/External_Dependencies/External_namespace_usage_per_internal_module_sorted_for_Typescript.cypher\")\n",
+ "external_namespaces_used_by_internal_modules.head(40)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bb458f01",
+ "metadata": {},
+ "source": [
+ "#### Table 6c - Top 15 used external modules with the internal modules that use them the most\n",
+ "\n",
+ "The following table uses pivot to show the internal modules in columns, the external modules in rows and the number of internal elements using them as values."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fd9667a9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Calculate the percentage for each value based on the global sum of all values\n",
+ "def percentage_global(data_frame : pd.DataFrame):\n",
+ " total = data_frame.sum().sum()\n",
+ " return data_frame / total * 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4ae9ada4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_modules_used_by_internal_modules_pivot = external_modules_used_by_internal_modules.copy()\n",
+ "\n",
+ "# Every row represents the number of external module\n",
+ "external_modules_used_by_internal_modules_pivot=external_modules_used_by_internal_modules_pivot.pivot(index='externalModuleName', columns='internalModuleName', values='numberOfExternalDeclarationCaller')\n",
+ "\n",
+ "# Sort by column sum and then take only the first 10 columns\n",
+ "sum_of_external_packages_per_artifact = external_modules_used_by_internal_modules_pivot.sum()\n",
+ "external_modules_used_by_internal_modules_pivot = external_modules_used_by_internal_modules_pivot[sum_of_external_packages_per_artifact.sort_values(ascending=False).index[:15]]\n",
+ "\n",
+ "# Fill missing values with zeroes\n",
+ "external_modules_used_by_internal_modules_pivot.fillna(0, inplace=True)\n",
+ "\n",
+ "external_modules_used_by_internal_modules_pivot.astype('int')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9b1fed8e",
+ "metadata": {},
+ "source": [
+ "#### Table 6d - Top 15 used external namespaces with the internal modules that use them the most\n",
+ "\n",
+ "The following table uses pivot to show the internal modules in columns, the external namespaces in rows and the number of internal elements using them as values."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "845099fc",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_namespaces_used_by_internal_modules_pivot = external_namespaces_used_by_internal_modules.copy()\n",
+ "\n",
+ "# Every row represents the number of external module\n",
+ "external_namespaces_used_by_internal_modules_pivot=external_namespaces_used_by_internal_modules_pivot.pivot(index='externalNamespaceName', columns='internalModuleName', values='numberOfExternalDeclarationCaller')\n",
+ "\n",
+ "# Sort by column sum and then take only the first 10 columns\n",
+ "sum_of_external_second_level_packages_per_artifact = external_namespaces_used_by_internal_modules_pivot.sum()\n",
+ "external_namespaces_used_by_internal_modules_pivot = external_namespaces_used_by_internal_modules_pivot[sum_of_external_second_level_packages_per_artifact.sort_values(ascending=False).index[:15]]\n",
+ "\n",
+ "# Fill missing values with zeroes\n",
+ "external_namespaces_used_by_internal_modules_pivot.fillna(0, inplace=True)\n",
+ "\n",
+ "external_namespaces_used_by_internal_modules_pivot.astype('int')"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "4fb87c8a",
+ "metadata": {},
+ "source": [
+ "### Table 6e - External usage per internal module and its elements\n",
+ "\n",
+ "This table lists internal elements and the modules they belong to that use many different external declarations of a specific external module. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "58a19ad7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Sort by number of packages descending\n",
+ "internal_modules_with_highest_external_declaration_usage = external_modules_used_by_internal_modules.copy()\n",
+ "internal_modules_with_highest_external_declaration_usage.sort_values(by=['numberOfAllExternalDeclarationsUsedInInternalModule','internalModuleName'], ascending=[False, True]).reset_index(drop=True)\n",
+ "internal_modules_with_highest_external_declaration_usage=internal_modules_with_highest_external_declaration_usage[['internalModuleName', 'numberOfAllExternalDeclarationsUsedInInternalModule', 'numberOfAllElementsInInternalModule']]\n",
+ "internal_modules_with_highest_external_declaration_usage=internal_modules_with_highest_external_declaration_usage.drop_duplicates()\n",
+ "internal_modules_with_highest_external_declaration_usage.head(40)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "43ec339b",
+ "metadata": {},
+ "source": [
+ "#### Table 6 Chart 1 - Top 15 external dependency using artifacts and their external packages stacked\n",
+ "\n",
+ "The following chart shows the top 15 external package using artifacts and breaks down which external packages they use in how many different internal packages with stacked bars. \n",
+ "\n",
+ "Note that every external dependency is counted separately so that if on internal package uses two external packages it will be displayed for both and so stacked twice. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9d8e8bb0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if external_modules_used_by_internal_modules_pivot.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ " axes = external_modules_used_by_internal_modules_pivot.transpose().plot(\n",
+ " kind='bar', \n",
+ " grid=True,\n",
+ " title='External module usage by internal modules', \n",
+ " xlabel='internal module',\n",
+ " ylabel='number of elements',\n",
+ " stacked=True,\n",
+ " legend=True,\n",
+ " cmap=main_color_map\n",
+ " ).legend(bbox_to_anchor=(1.0, 1.0))\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2d577c45",
+ "metadata": {},
+ "source": [
+ "#### Table 6 Chart 2 - Top 15 external dependency using artifacts and their external packages (first 2 levels) stacked\n",
+ "\n",
+ "The following chart shows the top 15 external package using artifacts and breaks down which external packages (first 2 levels) are used in how many different internal packages with stacked bars. \n",
+ "\n",
+ "Note that every external dependency is counted separately so that if on internal package uses two external packages it will be displayed for both and so stacked twice. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "17fc1572",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if external_namespaces_used_by_internal_modules_pivot.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ " axes = external_namespaces_used_by_internal_modules_pivot.transpose().plot(\n",
+ " kind='bar', \n",
+ " grid=True,\n",
+ " title='External namespaces usage by internal modules', \n",
+ " xlabel='internal module',\n",
+ " ylabel='number of internal elements',\n",
+ " stacked=True,\n",
+ " legend=True,\n",
+ " cmap=main_color_map\n",
+ " ).legend(bbox_to_anchor=(1.0, 1.0))\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "id": "5b420f59",
+ "metadata": {},
+ "source": [
+ "### Table 7 - External module usage distribution per internal element\n",
+ "\n",
+ "This table shows how many internal elements use one external module, how many use two, etc. .\n",
+ "This gives an overview of the distribution of external module calls and the overall coupling to external libraries. The higher the count of distinct external modules the lower should be the count of internal elements that use them. \n",
+ "More details about which types have the highest external package dependency usage can be in the tables 4 and 5 above.\n",
+ "\n",
+ "Only the last 40 entries are shown. The whole table can be found in the following CSV report:\n",
+ "`External_module_usage_per_internal_module_distribution_for_Typescript`\n",
+ "\n",
+ "**Columns:**\n",
+ "- *internalModuleName* is the internal module that uses at least one external module. All other columns refer to it.\n",
+ "- *numberOfAllInternalElements* the total number of all elements that are exported by the internal module\n",
+ "- *externalModuleCount* is the number of distinct external modules used by the internal module\n",
+ "- *internalElementCount* is the number of distinct internal elements that use at least one external one\n",
+ "- *internalElementsCallingExternalRate* is internalElementCount / numberOfAllInternalElements * 100 (in %)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d750524a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_package_usage_per_artifact_distribution = query_cypher_to_data_frame(\"../cypher/External_Dependencies/External_module_usage_per_internal_module_distribution_for_Typescript.cypher\")\n",
+ "external_package_usage_per_artifact_distribution_truncated=external_package_usage_per_artifact_distribution[['internalModuleName', 'numberOfAllInternalElements', 'externalModuleCount', 'internalElementCount', 'internalElementsCallingExternalRate']].head(40)\n",
+ "external_package_usage_per_artifact_distribution_truncated"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f90caf44",
+ "metadata": {},
+ "source": [
+ "# TODO"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "055e5a36",
+ "metadata": {},
+ "source": [
+ "### Table 8 - External package usage aggregated\n",
+ "\n",
+ "This table lists all artifacts and their external package dependencies usage aggregated over internal packages. \n",
+ "\n",
+ "The intention behind this is to find artifacts that use an external dependency across multiple internal packages. This might be intended for frameworks and standardized libraries and helps to quantify how widely those are used. For some external dependencies it might be beneficial to only access it from one package and provide an abstraction for internal usage following a [Hexagonal architecture](https://alistair.cockburn.us/hexagonal-architecture). Thus, this table may also help in finding application for the Hexagonal architecture or similar approaches (Domain Driven Design Anti Corruption Layer). After all it is easier to update or replace such external dependencies when they are used in specific areas and not all over the code.\n",
+ "\n",
+ "Only the last 40 entries are shown. The whole table can be found in the following CSV report:\n",
+ "`External_module_usage_per_internal_module_aggregated_for_Typescript`\n",
+ "\n",
+ "**Columns:**\n",
+ "- *internalModuleName* that contains the type that calls the external package\n",
+ "- *internalModuleElementsCount* is the total count of packages in the internal module\n",
+ "- *numberOfExternalModules* the number of distinct external packages used\n",
+ "- *[min,max,med,avg,std]NumberOfInternalModules* provide statistics based on each external package and its package usage within the internal module\n",
+ "- *[min,max,med,avg,std]NumberOfInternalElements* provide statistics based on each external package and its type usage within the internal module\n",
+ "- *[min,max,med,avg,std]NumberOfTypePercentage* provide statistics in % based on each external package and its type usage within the internal module in respect to the overall count of packages in the internal module\n",
+ "- *numberOfinternalElements* in the internal module where the *numberOfExternalModules* applies\n",
+ "- *numberOfTypesPercentage* in the internal module where the *numberOfExternalModules* applies in %"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7850d0a2",
+ "metadata": {},
+ "source": [
+ "#### Table 8a - External module usage aggregated - count of internal modules"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6d01860a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_package_usage_aggregated = query_cypher_to_data_frame(\"../cypher/External_Dependencies/External_module_usage_per_internal_module_aggregated_for_Typescript.cypher\")\n",
+ "\n",
+ "external_package_usage_aggregated_packages = external_package_usage_aggregated[['internalModuleName', 'internalModuleElementsCount', 'numberOfExternalModules', 'minNumberOfInternalModules', 'medNumberOfInternalModules', 'avgNumberOfInternalModules', 'maxNumberOfInternalModules', 'stdNumberOfInternalModules']]\n",
+ "external_package_usage_aggregated_packages.head(30)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8c476382",
+ "metadata": {},
+ "source": [
+ "#### Table 8b - External module usage aggregated - count of internal elements"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "40392b95",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_package_usage_aggregated_types = external_package_usage_aggregated[['internalModuleName', 'internalModuleElementsCount', 'numberOfExternalModules', 'minNumberOfInternalElements', 'medNumberOfInternalElements', 'avgNumberOfInternalElements', 'maxNumberOfInternalElements', 'stdNumberOfInternalElements']]\n",
+ "external_package_usage_aggregated_types.head(30)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0eac5b93",
+ "metadata": {},
+ "source": [
+ "#### Table 8c - External module usage aggregated - percentage of internal elements"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "260cc520",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "external_package_usage_aggregated_types_percentage = external_package_usage_aggregated[['internalModuleName', 'internalModuleElementsCount', 'numberOfExternalModules', 'minNumberOfInternalElementsPercentage', 'medNumberOfInternalElementsPercentage', 'avgNumberOfInternalElementsPercentage', 'maxNumberOfInternalElementsPercentage', 'stdNumberOfInternalElementsPercentage']]\n",
+ "external_package_usage_aggregated_types_percentage.head(30)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d1a16e29",
+ "metadata": {},
+ "source": [
+ "#### Table 8 Chart 1 - External module usage - max percentage of internal types\n",
+ "\n",
+ "This chart shows per internal module the maximum percentage of internal packages (compared to all packages in that internal module) that use one specific external package. \n",
+ "\n",
+ "**Example:** One internal module might use 10 external packages where 7 of them are used in one internal package, 2 of them are used in two packages and one external dependency is used in 5 packages. So for this internal module there will be a point at x = 10 (external packages used by the internal module) and 5 (max internal packages). Instead of the count the percentage of internal packages compared to all packages in that internal module is used to get a normalized plot."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ad1db8af",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def annotate_plot(data_frame: pd.DataFrame, index: int):\n",
+ " \"\"\"\n",
+ " Annotates the data points identified by the \"index\" in the plot of the \"data_frame\" \n",
+ " \"\"\"\n",
+ " x_position = data_frame.numberOfExternalModules[index].item()\n",
+ " y_position = data_frame.maxNumberOfInternalElementsPercentage[index].item()\n",
+ " artifact_name = data_frame.internalModuleName[index].item()\n",
+ "\n",
+ " label_box=dict(boxstyle=\"round4,pad=0.5\", fc=\"w\", alpha=0.8)\n",
+ " plot.annotate(artifact_name\n",
+ " ,xy=(x_position, y_position)\n",
+ " ,xycoords='data'\n",
+ " ,xytext=(-30, -15)\n",
+ " ,textcoords='offset points'\n",
+ " ,size=6\n",
+ " ,bbox=label_box\n",
+ " ,arrowprops=dict(arrowstyle=\"-|>\", mutation_scale=10, color=\"black\")\n",
+ " )\n",
+ "\n",
+ "def index_of_sorted(data_frame: pd.DataFrame, highest: list[str] = []):\n",
+ " \"\"\"\n",
+ " Sorts the \"data_frame\" by columns 'numberOfExternalModules','maxNumberOfInternalElementsPercentage','internalModuleElementsCount', 'internalModuleName'\n",
+ " and returns the index of the first row.\n",
+ " Columns that are contained in the list of strings parameter \"highest\" will be sorted descending (highest first).\n",
+ " \"\"\"\n",
+ " by = ['numberOfExternalModules','maxNumberOfInternalElementsPercentage','internalModuleElementsCount', 'internalModuleName']\n",
+ " ascending = [('numberOfExternalModules' not in highest), ('maxNumberOfInternalElementsPercentage' not in highest), False, True]\n",
+ " return data_frame.sort_values(by=by, ascending=ascending).head(1).index"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "615238d5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if external_package_usage_aggregated.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ " axes = external_package_usage_aggregated.plot(\n",
+ " kind='scatter',\n",
+ " title='External package usage - max internal packages %', \n",
+ " x='numberOfExternalModules',\n",
+ " y='maxNumberOfInternalElementsPercentage',\n",
+ " s='internalModuleElementsCount',\n",
+ " c='stdNumberOfInternalElementsPercentage',\n",
+ " xlabel='external module count',\n",
+ " ylabel='max percentage of internal elements',\n",
+ " cmap=main_color_map,\n",
+ " )\n",
+ "\n",
+ " # Annotate the largest internal module with the highest number of external packages and max number of packages in percentage\n",
+ " annotation_index = index_of_sorted(highest=['numberOfExternalModules','maxNumberOfInternalElementsPercentage'], data_frame=external_package_usage_aggregated)\n",
+ " annotate_plot(external_package_usage_aggregated, annotation_index)\n",
+ "\n",
+ "\n",
+ " # Annotate the largest internal module with the lowest number of external packages and the highest max number of packages in percentage\n",
+ " annotation_index = index_of_sorted(highest=['maxNumberOfInternalElementsPercentage'], data_frame=external_package_usage_aggregated)\n",
+ " annotate_plot(external_package_usage_aggregated, annotation_index)\n",
+ "\n",
+ " # Annotate the largest internal module with the lowest number of external packages and max number of packages in percentage\n",
+ " annotation_index = index_of_sorted(highest=[], data_frame=external_package_usage_aggregated)\n",
+ " annotate_plot(external_package_usage_aggregated, annotation_index)\n",
+ "\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9b7cff51",
+ "metadata": {},
+ "source": [
+ "#### Table 8 Chart 2 - External package usage - median percentage of internal types\n",
+ "\n",
+ "This chart shows per internal module the median (0.5 percentile) of internal packages (compared to all packages in that internal module) that use one specific external package. \n",
+ "\n",
+ "**Example:** One internal module might use 9 external packages where 3 of them are used in 1 internal package, 3 of them are used in 2 package and the last 3 ones are used in 3 packages. So for this internal module there will be a point at x = 10 (external packages used by the internal module) and 2 (median internal packages). Instead of the count the percentage of internal packages compared to all packages in that internal module is used to get a normalized plot."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "34d2595f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if external_package_usage_aggregated.empty:\n",
+ " print(\"No data to plot\")\n",
+ "else:\n",
+ " plot.figure();\n",
+ " axes = external_package_usage_aggregated.plot(\n",
+ " kind='scatter',\n",
+ " title='External package usage - median internal packages %', \n",
+ " x='numberOfExternalModules',\n",
+ " y='medNumberOfInternalElementsPercentage',\n",
+ " s='internalModuleElementsCount',\n",
+ " c='stdNumberOfInternalElementsPercentage',\n",
+ " xlabel='external module count',\n",
+ " ylabel='median percentage of internal elements',\n",
+ " cmap=main_color_map,\n",
+ " )\n",
+ " plot.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "46baa3c1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "driver.close()"
+ ]
+ }
+ ],
+ "metadata": {
+ "authors": [
+ {
+ "name": "JohT"
+ }
+ ],
+ "celltoolbar": "Tags",
+ "code_graph_analysis_pipeline_data_validation": "ValidateTypescriptModuleDependencies",
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.9"
+ },
+ "title": "Object Oriented Design Quality Metrics for Java with Neo4j"
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/scripts/downloader/downloadAntDesign.sh b/scripts/downloader/downloadAntDesign.sh
new file mode 100755
index 000000000..4fb463135
--- /dev/null
+++ b/scripts/downloader/downloadAntDesign.sh
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+
+# Downloads the Typescript project ant-design (https://github.com/ant-design/ant-design) from GitHub using git clone.
+# The source files are written into the "source" directory of the current analysis directory.
+# After scanning it with jQAssistant Typescript Plugin the resulting JSON will be moved into the "artifacts" directory.
+
+# Note: The #-framed blocks are those that are specific to this download.
+# The other parts of the script can be reused/copied as a reference to write other download scripts.
+
+# Note: This script is meant to be started within the temporary analysis directory (e.g. "temp/AnalysisName/")
+
+# Fail on any error (errexit = exit on first error, errtrace = error inherited from sub-shell ,pipefail exist on errors within piped commands)
+set -o errexit -o errtrace -o pipefail
+
+# Get the analysis name from the middle part of the current file name (without prefix "download" and without extension)
+SCRIPT_FILE_NAME="$(basename -- "${BASH_SOURCE[0]}")"
+SCRIPT_FILE_NAME_WITHOUT_EXTENSION="${SCRIPT_FILE_NAME%%.*}"
+SCRIPT_FILE_NAME_WITHOUT_PREFIX_AND_EXTENSION="${SCRIPT_FILE_NAME_WITHOUT_EXTENSION##download}"
+ANALYSIS_NAME="${SCRIPT_FILE_NAME_WITHOUT_PREFIX_AND_EXTENSION}"
+SOURCE_DIRECTORY=${SOURCE_DIRECTORY:-"source"} # Get the source repository directory (defaults to "source")
+
+echo "download${ANALYSIS_NAME}: SCRIPT_FILE_NAME=${SCRIPT_FILE_NAME}"
+echo "download${ANALYSIS_NAME}: SCRIPT_FILE_NAME_WITHOUT_EXTENSION=${SCRIPT_FILE_NAME_WITHOUT_EXTENSION}"
+echo "download${ANALYSIS_NAME}: ANALYSIS_NAME=${ANALYSIS_NAME}"
+
+# Read the first input argument containing the version(s) of the artifact(s)
+if [ "$#" -ne 1 ]; then
+ echo "Error (download${ANALYSIS_NAME}): Usage: $0 " >&2
+ exit 1
+fi
+PROJECT_VERSION=$1
+echo "download${ANALYSIS_NAME}: PROJECT_VERSION=${PROJECT_VERSION}"
+
+# Create runtime logs directory if it hasn't existed yet
+mkdir -p ./runtime/logs
+
+################################################################
+# Download ant-design source files to be analyzed
+################################################################
+if [ ! -d "${SOURCE_DIRECTORY}" ] ; then # only clone if source doesn't exist
+ git clone --branch "${PROJECT_VERSION}" https://github.com/ant-design/ant-design.git "${SOURCE_DIRECTORY}"
+fi
+(
+ cd "${SOURCE_DIRECTORY}" || exit
+ echo "download${ANALYSIS_NAME}: Installing dependencies..."
+ npm install || exit
+ echo "download${ANALYSIS_NAME}: Analyzing source..."
+ npx --yes @jqassistant/ts-lce >./../runtime/logs/jqassistant-typescript-scan.log 2>&1 || exit
+)
+mkdir -p artifacts
+mv -nv "${SOURCE_DIRECTORY}/.reports/jqa/ts-output.json" "artifacts/ts-ant-design-${PROJECT_VERSION}.json"
+################################################################
\ No newline at end of file
diff --git a/scripts/downloader/downloadReactRouter.sh b/scripts/downloader/downloadReactRouter.sh
index f7f90c8a7..390864699 100755
--- a/scripts/downloader/downloadReactRouter.sh
+++ b/scripts/downloader/downloadReactRouter.sh
@@ -44,7 +44,7 @@ git clone https://github.com/remix-run/react-router.git "${SOURCE_DIRECTORY}"
cd "${SOURCE_DIRECTORY}" || exit
git checkout "react-router@${PROJECT_VERSION}" || exit
pnpm install --frozen-lockfile || exit
- npx --yes @jqassistant/ts-lce >./../runtime/logs/jqassostant-typescript-scan.log 2>&1 || exit
+ npx --yes @jqassistant/ts-lce >./../runtime/logs/jqassistant-typescript-scan.log 2>&1 || exit
)
mkdir -p artifacts
mv -nv "${SOURCE_DIRECTORY}/.reports/jqa/ts-output.json" "artifacts/ts-react-router-${PROJECT_VERSION}.json"
diff --git a/scripts/examples/analyzeAntDesign.sh b/scripts/examples/analyzeAntDesign.sh
new file mode 100755
index 000000000..715505abe
--- /dev/null
+++ b/scripts/examples/analyzeAntDesign.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+# This is an example for the analysis of a the Typescript project "ant-design".
+# It includes the creation of the temporary directory, the working directory, the artifacts download and the analysis itself.
+
+# Note: The first (and only) parameter is the version of "ant-design" to analyze.
+# Note: This script is meant to be started in the root directory of this repository.
+
+# Fail on any error ("-e" = exit on first error, "-o pipefail" exist on errors within piped commands)
+set -o errexit -o pipefail
+
+# Read the first input argument containing the version of the artifacts
+if [ "$#" -ne 1 ]; then
+ echo "analyzerAntDesign Error: Usage: $0 " >&2
+ exit 1
+fi
+projectVersion=$1
+
+# Check if environment variable is set
+if [ -z "${NEO4J_INITIAL_PASSWORD}" ]; then
+ echo "analyzerAntDesign: Error: Requires environment variable NEO4J_INITIAL_PASSWORD to be set first. Use 'export NEO4J_INITIAL_PASSWORD='."
+ exit 1
+fi
+
+# Create the temporary directory for all analysis projects.
+mkdir -p ./temp
+cd ./temp
+
+# Create the working directory for this specific analysis.
+mkdir -p "./ant-design-${projectVersion}"
+cd "./ant-design-${projectVersion}"
+
+# Create the artifacts directory that will contain the code to be analyzed.
+mkdir -p ./artifacts
+
+# Download AxonFramework artifacts (jar files) from Maven
+./../../scripts/downloader/downloadAntDesign.sh "${projectVersion}"
+
+# Start the analysis
+./../../scripts/analysis/analyze.sh
\ No newline at end of file
diff --git a/scripts/importGitLog.sh b/scripts/importGitLog.sh
index 548928d92..73d611df2 100755
--- a/scripts/importGitLog.sh
+++ b/scripts/importGitLog.sh
@@ -42,7 +42,9 @@ while [[ $# -gt 0 ]]; do
done
# Check if the repository is actually a git repository
-if ! (cd "${repository}" || exit; git rev-parse --git-dir 2> /dev/null || exit); then
+if [ ! -d "${repository}/.git" ]; then
+#The following line would also take upper directories into account which isn't what we want here:
+#if ! (cd "${repository}" || exit; git rev-parse --git-dir 2> /dev/null || exit); then
echo "importGitLog: Import skipped. ${repository} is not a git repository."
exit 0
fi
diff --git a/scripts/prepareAnalysis.sh b/scripts/prepareAnalysis.sh
index 242c37f17..40d9391c7 100644
--- a/scripts/prepareAnalysis.sh
+++ b/scripts/prepareAnalysis.sh
@@ -61,7 +61,7 @@ execute_cypher "${CYPHER_DIR}/Create_Java_Type_index_for_full_qualified_name.cyp
execute_cypher "${CYPHER_DIR}/Create_Typescript_index_for_full_qualified_name.cypher"
# Preparation - Enrich Graph for Typescript by adding "module" and "name" properties
-execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Add_name_and_module_properties.cypher"
+execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Add_module_properties.cypher"
# Preparation - Enrich Graph for Typescript by adding relationships between Modules with the same globalFqn
execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Add_RESOLVES_TO_relationship_for_matching_modules.cypher"
diff --git a/scripts/reports/ExternalDependenciesCsv.sh b/scripts/reports/ExternalDependenciesCsv.sh
index ed21676ba..db854e644 100755
--- a/scripts/reports/ExternalDependenciesCsv.sh
+++ b/scripts/reports/ExternalDependenciesCsv.sh
@@ -39,7 +39,9 @@ EXTERNAL_DEPENDENCIES_CYPHER_DIR="${CYPHER_DIR}/External_Dependencies"
# Check if there are already labels for external Java types and create them otherwise
execute_cypher_queries_until_results "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/List_external_Java_types_used.cypher" \
- "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/Label_external_types_and_annotations.cypher"
+ "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/Label_external_types_and_annotations.cypher" >/dev/null
+
+# CSV reports for Java Packages
execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_package_usage_overall.cypher" > "${FULL_REPORT_DIRECTORY}/External_package_usage_overall.csv"
execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_package_usage_spread.cypher" > "${FULL_REPORT_DIRECTORY}/External_package_usage_spread.csv"
@@ -56,5 +58,19 @@ execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_second_level_packag
execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/Maven_POMs_and_their_declared_dependencies.cypher" > "${FULL_REPORT_DIRECTORY}/Maven_POM_dependencies.csv"
+# CSV reports for Typescript Modules
+
+execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_module_usage_overall_for_Typescript.cypher" > "${FULL_REPORT_DIRECTORY}/External_module_usage_overall_for_Typescript.csv"
+execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_module_usage_spread_for_Typescript.cypher" > "${FULL_REPORT_DIRECTORY}/External_module_usage_spread_for_Typescript.csv"
+
+execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_namespace_usage_overall_for_Typescript.cypher" > "${FULL_REPORT_DIRECTORY}/External_namespace_usage_overall_for_Typescript.csv"
+execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_namespace_usage_spread_for_Typescript.cypher" > "${FULL_REPORT_DIRECTORY}/External_namespace_usage_spread_for_Typescript.csv"
+
+execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_module_usage_per_internal_module_sorted_for_Typescript.cypher" > "${FULL_REPORT_DIRECTORY}/External_module_usage_per_internal_module_sorted_for_Typescript.csv"
+execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_namespace_usage_per_internal_module_sorted_for_Typescript.cypher" > "${FULL_REPORT_DIRECTORY}/External_namespace_usage_per_internal_module_sorted_for_Typescript.csv"
+
+execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_module_usage_per_internal_module_aggregated_for_Typescript.cypher" > "${FULL_REPORT_DIRECTORY}/External_module_usage_per_internal_module_aggregated_for_Typescript.csv"
+execute_cypher "${EXTERNAL_DEPENDENCIES_CYPHER_DIR}/External_module_usage_per_internal_module_distribution_for_Typescript.cypher" > "${FULL_REPORT_DIRECTORY}/External_module_usage_per_internal_module_distribution_for_Typescript.csv"
+
# Clean-up after report generation. Empty reports will be deleted.
source "${SCRIPTS_DIR}/cleanupAfterReportGeneration.sh" "${FULL_REPORT_DIRECTORY}"
\ No newline at end of file