@@ -14,28 +14,22 @@ export class NodePackageManager implements INodePackageManager {
14
14
private static NPM_REGISTRY_URL = "http://registry.npmjs.org/" ;
15
15
16
16
private versionsCache : IDictionary < string [ ] > ;
17
- private isLoaded : boolean ;
18
17
19
18
constructor ( private $logger : ILogger ,
20
19
private $errors : IErrors ,
21
20
private $httpClient : Server . IHttpClient ,
22
- private $staticConfig : IStaticConfig ,
23
- private $fs : IFileSystem ) {
21
+ private $fs : IFileSystem ,
22
+ private $lockfile : ILockFile ) {
24
23
this . versionsCache = { } ;
24
+ this . load ( ) . wait ( ) ;
25
25
}
26
26
27
- public getCacheRootPath ( ) : IFuture < string > {
28
- return ( ( ) => {
29
- this . load ( ) . wait ( ) ;
30
- return npm . cache ;
31
- } ) . future < string > ( ) ( ) ;
27
+ public getCacheRootPath ( ) : string {
28
+ return npm . cache ;
32
29
}
33
30
34
31
public addToCache ( packageName : string , version : string ) : IFuture < void > {
35
- return ( ( ) => {
36
- this . load ( ) . wait ( ) ;
37
- this . addToCacheCore ( packageName , version ) . wait ( ) ;
38
- } ) . future < void > ( ) ( ) ;
32
+ return this . addToCacheCore ( packageName , version ) ;
39
33
}
40
34
41
35
public load ( config ?: any ) : IFuture < void > {
@@ -52,29 +46,21 @@ export class NodePackageManager implements INodePackageManager {
52
46
53
47
public install ( packageName : string , opts ?: INpmInstallOptions ) : IFuture < string > {
54
48
return ( ( ) => {
55
- try {
56
- this . load ( ) . wait ( ) ; // It's obligatory to execute load before whatever npm function
49
+ this . $lockfile . lock ( ) . wait ( ) ;
57
50
51
+ try {
58
52
var packageToInstall = packageName ;
59
53
var pathToSave = ( opts && opts . pathToSave ) || npm . cache ;
60
54
var version = ( opts && opts . version ) || null ;
61
- var isSemanticVersioningDisabled = options . frameworkPath ? true : false ; // We need to disable sem versioning for local packages
62
-
63
- if ( version ) {
64
- this . validateVersion ( packageName , version ) . wait ( ) ;
65
- packageToInstall = packageName + "@" + version ;
66
- }
67
55
68
- this . installCore ( packageToInstall , pathToSave , isSemanticVersioningDisabled ) . wait ( ) ;
56
+ return this . installCore ( packageToInstall , pathToSave , version ) . wait ( ) ;
69
57
} catch ( error ) {
70
58
this . $logger . debug ( error ) ;
71
- this . $errors . fail ( NodePackageManager . NPM_LOAD_FAILED ) ;
59
+ this . $errors . fail ( "%s. Error: %s" , NodePackageManager . NPM_LOAD_FAILED , error ) ;
60
+ } finally {
61
+ this . $lockfile . unlock ( ) . wait ( ) ;
72
62
}
73
63
74
- var pathToNodeModules = path . join ( pathToSave , "node_modules" ) ;
75
- var folders = this . $fs . readDirectory ( pathToNodeModules ) . wait ( ) ;
76
- return path . join ( pathToNodeModules , folders [ 0 ] ) ;
77
-
78
64
} ) . future < string > ( ) ( ) ;
79
65
}
80
66
@@ -86,21 +72,39 @@ export class NodePackageManager implements INodePackageManager {
86
72
} ) . future < string > ( ) ( ) ;
87
73
}
88
74
89
- private installCore ( packageName : string , pathToSave : string , isSemanticVersioningDisabled : boolean ) : IFuture < void > {
90
- var currentVersion = this . $staticConfig . version ;
91
- if ( ! semver . valid ( currentVersion ) ) {
92
- this . $errors . fail ( "Invalid version." ) ;
93
- }
75
+ private installCore ( packageName : string , pathToSave : string , version : string ) : IFuture < string > {
76
+ return ( ( ) => {
77
+ if ( options . frameworkPath ) {
78
+ if ( this . $fs . getFsStats ( options . frameworkPath ) . wait ( ) . isFile ( ) ) {
79
+ this . npmInstall ( packageName , pathToSave , version ) . wait ( ) ;
80
+ var pathToNodeModules = path . join ( pathToSave , "node_modules" ) ;
81
+ var folders = this . $fs . readDirectory ( pathToNodeModules ) . wait ( ) ;
82
+ return path . join ( pathToNodeModules , folders [ 0 ] ) ;
83
+ }
84
+ return options . frameworkPath ;
85
+ } else {
86
+ var version = version || this . getLatestVersion ( packageName ) . wait ( ) ;
87
+ var packagePath = path . join ( npm . cache , packageName , version , "package" ) ;
88
+ if ( ! this . isPackageCached ( packagePath ) . wait ( ) ) {
89
+ this . addToCacheCore ( packageName , version ) . wait ( ) ;
90
+ }
94
91
95
- if ( ! isSemanticVersioningDisabled ) {
96
- var incrementedVersion = semver . inc ( currentVersion , constants . ReleaseType . MINOR ) ;
97
- if ( packageName . indexOf ( "@" ) < 0 ) {
98
- packageName = packageName + "@<" + incrementedVersion ;
92
+ if ( ! this . isPackageUnpacked ( packagePath ) . wait ( ) ) {
93
+ this . cacheUnpack ( packageName , version ) . wait ( ) ;
94
+ }
95
+ return packagePath ;
99
96
}
100
- }
97
+ } ) . future < string > ( ) ( ) ;
98
+ }
101
99
100
+ private npmInstall ( packageName : string , pathToSave : string , version : string ) : IFuture < void > {
102
101
this . $logger . out ( "Installing " , packageName ) ;
103
102
103
+ var incrementedVersion = semver . inc ( version , constants . ReleaseType . MINOR ) ;
104
+ if ( ! options . frameworkPath && packageName . indexOf ( "@" ) < 0 ) {
105
+ packageName = packageName + "@<" + incrementedVersion ;
106
+ }
107
+
104
108
var future = new Future < void > ( ) ;
105
109
npm . commands [ "install" ] ( pathToSave , packageName , ( err : Error , data : any ) => {
106
110
if ( err ) {
@@ -113,6 +117,17 @@ export class NodePackageManager implements INodePackageManager {
113
117
return future ;
114
118
}
115
119
120
+ private isPackageCached ( packagePath : string ) : IFuture < boolean > {
121
+ return this . $fs . exists ( packagePath ) ;
122
+ }
123
+
124
+ private isPackageUnpacked ( packagePath : string ) : IFuture < boolean > {
125
+ return ( ( ) => {
126
+ return this . $fs . getFsStats ( packagePath ) . wait ( ) . isDirectory ( ) &&
127
+ helpers . enumerateFilesInDirectorySync ( packagePath ) . length > 1 ;
128
+ } ) . future < boolean > ( ) ( ) ;
129
+ }
130
+
116
131
private addToCacheCore ( packageName : string , version : string ) : IFuture < void > {
117
132
var future = new Future < void > ( ) ;
118
133
npm . commands [ "cache" ] . add ( packageName , version , undefined , ( err : Error , data : any ) => {
@@ -150,14 +165,5 @@ export class NodePackageManager implements INodePackageManager {
150
165
return this . versionsCache [ packageName ] ;
151
166
} ) . future < string [ ] > ( ) ( ) ;
152
167
}
153
-
154
- private validateVersion ( packageName : string , version : string ) : IFuture < void > {
155
- return ( ( ) => {
156
- var versions = this . getAvailableVersions ( packageName ) . wait ( ) ;
157
- if ( ! _ . contains ( versions , version ) ) {
158
- this . $errors . fail ( "Invalid version. Valid versions are: %s" , helpers . formatListOfNames ( versions , "and" ) ) ;
159
- }
160
- } ) . future < void > ( ) ( ) ;
161
- }
162
168
}
163
169
$injector . register ( "npm" , NodePackageManager ) ;
0 commit comments