Skip to content

Commit 91b7647

Browse files
authored
Merge pull request #547 from JohT/feature/separate-npm-dev-dependencies
Distinguish between dev and non dev NPM package dependencies
2 parents 6121494 + eead6c8 commit 91b7647

12 files changed

+135
-28
lines changed

COMMANDS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,12 @@ The [analyze.sh](./scripts/analysis/analyze.sh) command comes with these command
7676

7777
- `--profile Neo4jv5` uses the older long term support (march 2025) version v5.26.x of Neo4j and suitable compatible versions of plugins and JQAssistant. Without specifying a profile, the newest versions will be used. Other profiles can be found in the directory [scripts/profiles](./scripts/profiles/).
7878

79-
- `--profile Neo4j-latest-continue-on-scan-errors` is based on the default profile (`Neo4j-latest`) but uses the jQAssistant configuration template [template-neo4j-remote-jqassistant-continue-on-error.yaml](./scripts/configuration/template-neo4j-remote-jqassistant-continue-on-error.yaml) to continue on scan error instead of failing fast. This is temporarily useful when there is a known error that needs to be ignored. It is still recommended to use the default profile and fail fast if there is something wrong. Other profiles can be found in the directory [scripts/profiles](./scripts/profiles/).
79+
- `--profile Neo4j-latest-continue-on-scan-errors` is based on the default profile (`Neo4j-latest`) but uses the jQAssistant configuration template [template-neo4jv5-jqassistant-continue-on-error.yaml](./scripts/configuration/template-neo4jv5-jqassistant-continue-on-error.yaml) to continue on scan error instead of failing fast. This is temporarily useful when there is a known error that needs to be ignored. It is still recommended to use the default profile and fail fast if there is something wrong. Other profiles can be found in the directory [scripts/profiles](./scripts/profiles/).
8080

8181
- `--profile Neo4j-latest-low-memory` is based on the default profile (`Neo4j-latest`) but uses only half of the memory (RAM) as configured in [template-neo4j-low-memory.conf](./scripts/configuration/template-neo4j-low-memory.conf). This is useful for the analysis of smaller codebases with less resources. Other profiles can be found in the directory [scripts/profiles](./scripts/profiles/).
8282

83+
- `--profile Neo4j-latest-low-memory-continue-on-scan-errors` is based on the default profile (`Neo4j-latest`) but uses only half of the memory (RAM) as configured in [template-neo4j-low-memory.conf](./scripts/configuration/template-neo4j-low-memory.conf) and the jQAssistant configuration template [template-neo4jv5-jqassistant-continue-on-error.yaml](./scripts/configuration/template-neo4jv5-jqassistant-continue-on-error.yaml) to continue on scan error instead of failing fast. This is temporarily useful when there is a known error that needs to be ignored. It is still recommended to use the default profile and fail fast if there is something wrong. Other profiles can be found in the directory [scripts/profiles](./scripts/profiles/).
84+
8385
- `--profile Neo4j-latest-high-memory` is based on the default profile (`Neo4j-latest`) but uses more memory (RAM) as configured in [template-neo4j-high-memory.conf](./scripts/configuration/template-neo4j-high-memory.conf). This is useful for the analysis of larger codebases with more resources. Other profiles can be found in the directory [scripts/profiles](./scripts/profiles/).
8486

8587
- `--explore` activates the "explore" mode where no reports are generated. Furthermore, Neo4j won't be stopped at the end of the script and will therefore continue running. This makes it easy to just set everything up but then use the running Neo4j server to explore the data manually.

cypher/Internal_Dependencies/NPM_Package_build_levels_for_graphviz.cypher

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
WITH *, round((normalizedWeight * 5) + 1, 2) AS penWidth
1717
WITH *, "\\n(level " + coalesce(source.maxDistanceFromSource + "/" + maxLevel, "?") + ")" AS sourceLevelInfo
1818
WITH *, "\\n(level " + coalesce(target.maxDistanceFromSource + "/" + maxLevel, "?") + ")" AS targetLevelInfo
19-
WITH *, source.name + sourceLevelInfo AS fullSourceName
20-
WITH *, target.name + targetLevelInfo AS fullTargetName
19+
WITH *, CASE WHEN source:NpmDevPackage THEN "\\n[dev]" ELSE "" END AS sourceDevDependencyInfo
20+
WITH *, CASE WHEN target:NpmDevPackage THEN "\\n[dev]" ELSE "" END AS targetDevDependencyInfo
21+
WITH *, source.name + sourceLevelInfo + sourceDevDependencyInfo AS fullSourceName
22+
WITH *, target.name + targetLevelInfo + targetDevDependencyInfo AS fullTargetName
2123
WITH *, "\" -> \"" + fullTargetName
2224
+ "\" [label = " + dependency.weightByDependencyType + ";"
2325
+ " penwidth = " + penWidth + ";"

cypher/Path_Finding/Set_Parameters_NPM.cypher renamed to cypher/Path_Finding/Set_Parameters_NonDevNpmPackage.cypher

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
:params {
44
"dependencies_projection_language":"NPM",
5-
"dependencies_projection": "npm-package-path-finding",
6-
"dependencies_projection_node": "Package",
5+
"dependencies_projection": "npm-non-dev-package-path-finding",
6+
"dependencies_projection_node": "NpmNonDevPackage",
77
"dependencies_projection_weight_property": "weightByDependencyType",
88
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Label NPM packages as NpmDevPackage or NpmNonDevPackage based on incoming DEPENDS_ON. Requires Link_npm_packages_with_depends_on_relationships.cypher
2+
// For each package node, calculate the maximum `weightByDependencyType` across incoming
3+
// `DEPENDS_ON` relationships. If the max is 1 -> label `NpmDevPackage`; if > 1 -> label
4+
// `NpmNonDevPackage`. If the property is missing or < 1 then no label is added.
5+
// weightByDependencyType= 1 is a dev dependency, 2 is a regular dependency, and 3 is a peer dependency.
6+
7+
MATCH (packageNode:NPM:Package)
8+
OPTIONAL MATCH (packageNode)<-[dependsOnRel:DEPENDS_ON]-()
9+
WITH packageNode, max(dependsOnRel.weightByDependencyType) AS maxWeight
10+
11+
CALL {
12+
WITH packageNode, maxWeight
13+
FOREACH (_ IN CASE WHEN maxWeight = 1 THEN [1] ELSE [] END |
14+
SET packageNode:NpmDevPackage
15+
)
16+
17+
FOREACH (_ IN CASE WHEN maxWeight > 1 THEN [1] ELSE [] END |
18+
SET packageNode:NpmNonDevPackage
19+
)
20+
} IN TRANSACTIONS OF 1000 ROWS
21+
22+
RETURN count(packageNode) AS evaluatedPackages,
23+
sum(CASE WHEN maxWeight = 1 THEN 1 ELSE 0 END) AS numberOfNpmDevPackages,
24+
sum(CASE WHEN maxWeight > 1 THEN 1 ELSE 0 END) AS numberOfNpmNonDevPackages,
25+
sum(CASE WHEN maxWeight IS NULL THEN 1 ELSE 0 END) AS numberOfPackagesWithMissingWeight,
26+
sum(CASE WHEN maxWeight < 1 AND maxWeight IS NOT NULL THEN 1 ELSE 0 END) AS numberOfPackagesWithWeightBelowOne
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Remove NPM package type labels (idempotent).
2+
3+
MATCH (packageNode:NPM:Package)
4+
REMOVE packageNode:NpmDevPackage
5+
REMOVE packageNode:NpmNonDevPackage

scripts/findPathsToScan.sh

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,18 @@ else
5454
fi
5555

5656
if [ -d "./${SOURCE_DIRECTORY}" ] ; then
57+
# Scan package.json files for npm (nodes package manager) in the source directory
58+
# Since the following issue had been resolved, the scan can be done here again:
59+
# https://github.com/jqassistant-plugin/jqassistant-npm-plugin/issues/5
60+
npmPackageJsonFiles="$(findPackageJsonFiles "./${SOURCE_DIRECTORY}")"
61+
if [ -n "${npmPackageJsonFiles}" ]; then
62+
directoriesAndFilesToScan="$(appendNonEmpty "${directoriesAndFilesToScan}")${npmPackageJsonFiles}"
63+
fi
64+
5765
# Scan Typescript analysis json data files in the source directory
66+
# Since Typescript scan might produce duplicate fileName properties on File nodes,
67+
# it is done after the npm package.json scan, that breaks the scan on duplicate fileName properties.
68+
# This order fixes "XOException: Expected exactly one result, but got CompositeRowObject".
5869
typescriptAnalysisFiles="$(find -L "./${SOURCE_DIRECTORY}" \
5970
-type d -name "node_modules" -prune -o \
6071
-type d -name "dist" -prune -o \
@@ -69,14 +80,6 @@ if [ -d "./${SOURCE_DIRECTORY}" ] ; then
6980
directoriesAndFilesToScan="$(appendNonEmpty "${directoriesAndFilesToScan}")${typescriptAnalysisFiles}"
7081
fi
7182

72-
# Scan package.json files for npm (nodes package manager) in the source directory
73-
# Since the following issue had been resolved, the scan be done here again:
74-
# https://github.com/jqassistant-plugin/jqassistant-npm-plugin/issues/5
75-
npmPackageJsonFiles="$(findPackageJsonFiles "./${SOURCE_DIRECTORY}")"
76-
if [ -n "${npmPackageJsonFiles}" ]; then
77-
directoriesAndFilesToScan="$(appendNonEmpty "${directoriesAndFilesToScan}")${npmPackageJsonFiles}"
78-
fi
79-
8083
# Scan git repositories in the artifacts directory
8184
if [ "${IMPORT_GIT_LOG_DATA_IF_SOURCE_IS_PRESENT}" = "" ] || [ "${IMPORT_GIT_LOG_DATA_IF_SOURCE_IS_PRESENT}" = "plugin" ] ; then
8285
gitDirectories="$(find -L "./${SOURCE_DIRECTORY}" \

scripts/prepareAnalysis.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Remove_duplicate_CONTAINS_relations_bet
7979
execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Link_npm_dependencies_to_npm_packages.cypher"
8080
execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Link_npm_packages_with_depends_on_relationships.cypher"
8181
execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Enrich_npm_packages_with_dependency_counts.cypher"
82+
execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Remove_npm_dependency_type_labels.cypher"
83+
execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Label_npm_packages_by_dep_type.cypher"
8284
execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Link_projects_to_npm_packages.cypher"
8385
dataVerificationResult=$( execute_cypher "${TYPESCRIPT_CYPHER_DIR}/Verify_projects_linked_to_npm_packages.cypher" "${@}")
8486
if is_csv_column_greater_zero "${dataVerificationResult}" "unresolvedProjectsCount"; then
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
3+
# Sets all settings variables for a low memory, continue-on-error analysis with the latest version of Neo4j.
4+
# The chosen settings are tested to be compatible and working.
5+
6+
NEO4J_VERSION=${NEO4J_VERSION:-"2026.01.4"} # Neo4j Graph Database Version. Current versions: >= 2025.03.0. Version 4.4.42 and 5.26.5 are the previous LTS (long term support) versions as of April 2025.
7+
NEO4J_HTTP_TRANSACTION_ENDPOINT=${NEO4J_HTTP_TRANSACTION_ENDPOINT:-"db/neo4j/tx/commit"}
8+
NEO4J_CONFIG_TEMPLATE=${NEO4J_CONFIG_TEMPLATE:-"template-neo4j-low-memory.conf"}
9+
10+
# Awesome Procedures (APOC) Plugin for Neo4j
11+
NEO4J_APOC_PLUGIN_VERSION=${NEO4J_APOC_PLUGIN_VERSION:-"2026.01.4"}
12+
NEO4J_APOC_PLUGIN_EDITION=${NEO4J_APOC_PLUGIN_EDITION:-"core"}
13+
NEO4J_APOC_PLUGIN_GITHUB=${NEO4J_APOC_PLUGIN_GITHUB:-"neo4j/apoc"}
14+
15+
NEO4J_GDS_PLUGIN_VERSION=${NEO4J_GDS_PLUGIN_VERSION:-"2.26.0"}
16+
NEO4J_OPEN_GDS_PLUGIN_VERSION=${NEO4J_OPEN_GDS_PLUGIN_VERSION:-"2.26.0"}
17+
NEO4J_GDS_PLUGIN_EDITION=${NEO4J_GDS_PLUGIN_EDITION:-"open"}
18+
19+
JQASSISTANT_CLI_VERSION=${JQASSISTANT_CLI_VERSION:-"2.9.0"}
20+
JQASSISTANT_CLI_ARTIFACT=${JQASSISTANT_CLI_ARTIFACT:-"jqassistant-commandline-neo4jv5"}
21+
JQASSISTANT_CONFIG_TEMPLATE=${JQASSISTANT_CONFIG_TEMPLATE:-"template-neo4jv5-jqassistant-continue-on-error.yaml"}

scripts/reports/CentralityCsv.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -439,12 +439,12 @@ if createUndirectedDependencyProjection "${MODULE_LANGUAGE}" "${MODULE_PROJECTIO
439439
runUndirectedCentralityAlgorithms "${MODULE_PROJECTION_UNDIRECTED}" "${MODULE_NODE}"
440440
fi
441441

442-
# -- NPM Package Centrality ---------------------------------------
442+
# -- Non Dev NPM Package Centrality ---------------------------------------
443443

444444
NPM_LANGUAGE="dependencies_projection_language=NPM"
445-
NPM_PROJECTION="dependencies_projection=npm-package-centrality"
446-
NPM_PROJECTION_UNDIRECTED="dependencies_projection=npm-package-centrality-undirected"
447-
NPM_NODE="dependencies_projection_node=Package"
445+
NPM_PROJECTION="dependencies_projection=npm-non-dev-package-centrality"
446+
NPM_PROJECTION_UNDIRECTED="dependencies_projection=npm-non-dev-package-centrality-undirected"
447+
NPM_NODE="dependencies_projection_node=NpmNonDevPackage"
448448
NPM_WEIGHT="dependencies_projection_weight_property=weightByDependencyType"
449449

450450
if createDirectedDependencyProjection "${NPM_LANGUAGE}" "${NPM_PROJECTION}" "${NPM_NODE}" "${NPM_WEIGHT}"; then

scripts/reports/PathFindingCsv.sh

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,28 @@ if createDirectedDependencyProjection "${MODULE_LANGUAGE}" "${MODULE_PROJECTION}
140140
runPathFindingAlgorithms "${MODULE_PROJECTION}" "${MODULE_NODE}" "${MODULE_WEIGHT}"
141141
fi
142142

143-
# -- NPM Package Path Finding -------------------------------
143+
# -- Non Dev NPM Package Path Finding -------------------------------
144144

145145
NPM_LANGUAGE="dependencies_projection_language=NPM"
146-
NPM_PROJECTION="dependencies_projection=npm-package-path-finding"
147-
NPM_NODE="dependencies_projection_node=Package"
146+
NPM_PROJECTION="dependencies_projection=npm-non-dev-package-path-finding"
147+
NPM_NODE="dependencies_projection_node=NpmNonDevPackage"
148148
NPM_WEIGHT="dependencies_projection_weight_property=weightByDependencyType"
149149

150150
if createDirectedDependencyProjection "${NPM_LANGUAGE}" "${NPM_PROJECTION}" "${NPM_NODE}" "${NPM_WEIGHT}"; then
151151
runPathFindingAlgorithms "${NPM_PROJECTION}" "${NPM_NODE}" "${NPM_WEIGHT}"
152152
fi
153+
154+
# -- Dev NPM Package Path Finding -------------------------------
155+
156+
NPM_DEV_LANGUAGE="dependencies_projection_language=NPM"
157+
NPM_DEV_PROJECTION="dependencies_projection=npm-dev-package-path-finding"
158+
NPM_DEV_NODE="dependencies_projection_node=NpmDevPackage"
159+
NPM_DEV_WEIGHT="dependencies_projection_weight_property=weightByDependencyType"
160+
161+
if createDirectedDependencyProjection "${NPM_DEV_LANGUAGE}" "${NPM_DEV_PROJECTION}" "${NPM_DEV_NODE}" "${NPM_DEV_WEIGHT}"; then
162+
runPathFindingAlgorithms "${NPM_DEV_PROJECTION}" "${NPM_DEV_NODE}" "${NPM_DEV_WEIGHT}"
163+
fi
164+
153165
# ---------------------------------------------------------------
154166

155167
# Clean-up after report generation. Empty reports will be deleted.

0 commit comments

Comments
 (0)