2
2
3
3
import com .fasterxml .jackson .databind .JsonNode ;
4
4
import org .apache .commons .lang .StringUtils ;
5
+ import org .apache .commons .lang3 .ArrayUtils ;
5
6
import org .jfrog .build .extractor .npm .types .NpmPackageInfo ;
6
7
import org .jfrog .build .extractor .npm .types .NpmScope ;
7
8
import org .jfrog .build .extractor .scan .DependenciesTree ;
@@ -24,51 +25,47 @@ public class NpmDependencyTree {
24
25
* @return Tree of npm PackageInfos.
25
26
* @see NpmPackageInfo
26
27
*/
27
- public static DependenciesTree createDependenciesTree (JsonNode npmList ) {
28
+ public static DependenciesTree createDependenciesTree (JsonNode npmList , NpmScope scope ) {
28
29
DependenciesTree rootNode = new DependenciesTree ();
29
- populateDependenciesTree (rootNode , npmList .get ("dependencies" ));
30
+ populateDependenciesTree (rootNode , npmList .get ("dependencies" ), new String []{ npmList . get ( "name" ). asText () + ":" + npmList . get ( "version" ). asText ()}, scope );
30
31
for (DependenciesTree child : rootNode .getChildren ()) {
31
32
NpmPackageInfo packageInfo = (NpmPackageInfo ) child .getUserObject ();
32
33
child .setScopes (getScopes (packageInfo .getName (), packageInfo .getScope ()));
33
34
}
34
35
return rootNode ;
35
36
}
36
37
37
- private static void populateDependenciesTree (DependenciesTree scanTreeNode , JsonNode dependencies ) {
38
- if (dependencies == null ) {
38
+ /**
39
+ * Parses npm dependencies recursively and adds the collected dependencies to scanTreeNode.
40
+ *
41
+ * @param scanTreeNode - Output - The DependenciesTree to populate.
42
+ * @param dependencies - The dependencies json object generated by npm ls.
43
+ * @param pathToRoot - A path-to-root dependency list. The structure of each dependency in the list is 'dependency-name:dependency-version'.
44
+ */
45
+ private static void populateDependenciesTree (DependenciesTree scanTreeNode , JsonNode dependencies , String [] pathToRoot , NpmScope scope ) {
46
+ if (dependencies == null || pathToRoot == null ) {
39
47
return ;
40
48
}
41
49
42
50
dependencies .fields ().forEachRemaining (stringJsonNodeEntry -> {
43
51
String name = stringJsonNodeEntry .getKey ();
44
52
JsonNode versionNode = stringJsonNodeEntry .getValue ().get ("version" );
45
53
if (versionNode != null ) {
46
- addSubtree (stringJsonNodeEntry , scanTreeNode , name , versionNode .asText ()); // Mutual recursive call
54
+ addSubtree (stringJsonNodeEntry , scanTreeNode , name , versionNode .asText (), pathToRoot , scope ); // Mutual recursive call
47
55
}
48
56
});
49
57
}
50
58
51
- private static void addSubtree (Map .Entry <String , JsonNode > stringJsonNodeEntry , DependenciesTree node , String name , String version ) {
59
+ private static void addSubtree (Map .Entry <String , JsonNode > stringJsonNodeEntry , DependenciesTree node , String name , String version , String [] pathToRoot , NpmScope scope ) {
52
60
JsonNode jsonNode = stringJsonNodeEntry .getValue ();
53
- String devScope = ( isDev ( jsonNode ) ? NpmScope . DEVELOPMENT : NpmScope . PRODUCTION ) .toString ();
54
- NpmPackageInfo npmPackageInfo = new NpmPackageInfo (name , version , devScope );
61
+ String devScope = scope .toString ();
62
+ NpmPackageInfo npmPackageInfo = new NpmPackageInfo (name , version , devScope , pathToRoot );
55
63
JsonNode childDependencies = jsonNode .get ("dependencies" );
56
64
DependenciesTree childTreeNode = new DependenciesTree (npmPackageInfo );
57
- populateDependenciesTree (childTreeNode , childDependencies ); // Mutual recursive call
65
+ populateDependenciesTree (childTreeNode , childDependencies , ArrayUtils . insert ( 0 , pathToRoot , npmPackageInfo . toString ()), scope ); // Mutual recursive call
58
66
node .add (childTreeNode );
59
67
}
60
68
61
- /**
62
- * Return true if the input dependency is a dev dependency.
63
- *
64
- * @param jsonNode - The dependency node in the 'npm ls' results
65
- * @return true if the input dependency is a dev dependency
66
- */
67
- private static boolean isDev (JsonNode jsonNode ) {
68
- JsonNode development = jsonNode .get ("_development" );
69
- return development != null && development .asBoolean (false );
70
- }
71
-
72
69
/**
73
70
* Return a set of the relevant scopes. The set contains 'development' or 'production'. If the dependency has a
74
71
* custom scope, add it too.
0 commit comments