1
1
package org .jfrog .build .extractor .npm .extractor ;
2
2
3
3
import com .fasterxml .jackson .databind .JsonNode ;
4
- import org .apache .commons .lang3 . ObjectUtils ;
4
+ import org .apache .commons .lang . StringUtils ;
5
5
import org .jfrog .build .extractor .npm .types .NpmPackageInfo ;
6
6
import org .jfrog .build .extractor .npm .types .NpmScope ;
7
7
import org .jfrog .build .extractor .scan .DependenciesTree ;
8
+ import org .jfrog .build .extractor .scan .Scope ;
8
9
10
+ import java .util .HashSet ;
9
11
import java .util .Map ;
12
+ import java .util .Set ;
10
13
11
14
/**
12
15
* @author Yahav Itzhak
@@ -17,18 +20,21 @@ public class NpmDependencyTree {
17
20
/**
18
21
* Create a npm dependencies tree from the results of 'npm ls' command.
19
22
*
20
- * @param scope - 'production' or 'development'.
21
23
* @param npmList - Results of 'npm ls' command.
22
24
* @return Tree of npm PackageInfos.
23
25
* @see NpmPackageInfo
24
26
*/
25
- public static DependenciesTree createDependenciesTree (NpmScope scope , JsonNode npmList ) {
27
+ public static DependenciesTree createDependenciesTree (JsonNode npmList ) {
26
28
DependenciesTree rootNode = new DependenciesTree ();
27
- populateDependenciesTree (rootNode , scope , npmList .get ("dependencies" ));
29
+ populateDependenciesTree (rootNode , npmList .get ("dependencies" ));
30
+ for (DependenciesTree child : rootNode .getChildren ()) {
31
+ NpmPackageInfo packageInfo = (NpmPackageInfo ) child .getUserObject ();
32
+ child .setScopes (getScopes (packageInfo .getName (), packageInfo .getScope ()));
33
+ }
28
34
return rootNode ;
29
35
}
30
36
31
- private static void populateDependenciesTree (DependenciesTree scanTreeNode , NpmScope scope , JsonNode dependencies ) {
37
+ private static void populateDependenciesTree (DependenciesTree scanTreeNode , JsonNode dependencies ) {
32
38
if (dependencies == null ) {
33
39
return ;
34
40
}
@@ -37,16 +43,47 @@ private static void populateDependenciesTree(DependenciesTree scanTreeNode, NpmS
37
43
String name = stringJsonNodeEntry .getKey ();
38
44
JsonNode versionNode = stringJsonNodeEntry .getValue ().get ("version" );
39
45
if (versionNode != null ) {
40
- addSubtree (stringJsonNodeEntry , scanTreeNode , name , versionNode .asText (), scope ); // Mutual recursive call
46
+ addSubtree (stringJsonNodeEntry , scanTreeNode , name , versionNode .asText ()); // Mutual recursive call
41
47
}
42
48
});
43
49
}
44
50
45
- private static void addSubtree (Map .Entry <String , JsonNode > stringJsonNodeEntry , DependenciesTree node , String name , String version , NpmScope scope ) {
46
- NpmPackageInfo npmPackageInfo = new NpmPackageInfo (name , version , ObjectUtils .defaultIfNull (scope , "" ).toString ());
47
- JsonNode childDependencies = stringJsonNodeEntry .getValue ().get ("dependencies" );
51
+ private static void addSubtree (Map .Entry <String , JsonNode > stringJsonNodeEntry , DependenciesTree node , String name , String version ) {
52
+ JsonNode jsonNode = stringJsonNodeEntry .getValue ();
53
+ String devScope = (isDev (jsonNode ) ? NpmScope .DEVELOPMENT : NpmScope .PRODUCTION ).toString ();
54
+ NpmPackageInfo npmPackageInfo = new NpmPackageInfo (name , version , devScope );
55
+ JsonNode childDependencies = jsonNode .get ("dependencies" );
48
56
DependenciesTree childTreeNode = new DependenciesTree (npmPackageInfo );
49
- populateDependenciesTree (childTreeNode , scope , childDependencies ); // Mutual recursive call
57
+ populateDependenciesTree (childTreeNode , childDependencies ); // Mutual recursive call
50
58
node .add (childTreeNode );
51
59
}
60
+
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
+ /**
73
+ * Return a set of the relevant scopes. The set contains 'development' or 'production'. If the dependency has a
74
+ * custom scope, add it too.
75
+ *
76
+ * @param name - The name of the dependency
77
+ * @param devScope - 'development' or 'production'
78
+ * @return set of the relevant scopes
79
+ */
80
+ private static Set <Scope > getScopes (String name , String devScope ) {
81
+ Set <Scope > scopes = new HashSet <>();
82
+ scopes .add (new Scope (devScope ));
83
+ String customScope = StringUtils .substringBetween (name , "@" , "/" );
84
+ if (customScope != null ) {
85
+ scopes .add (new Scope (customScope ));
86
+ }
87
+ return scopes ;
88
+ }
52
89
}
0 commit comments