-
-
Notifications
You must be signed in to change notification settings - Fork 197
/
Copy pathnpm-installation-manager.ts
124 lines (104 loc) · 4.2 KB
/
npm-installation-manager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
///<reference path=".d.ts"/>
"use strict";
import path = require("path");
import semver = require("semver");
import npm = require("npm");
import constants = require("./constants");
export class NpmInstallationManager {
private static NPM_LOAD_FAILED = "Failed to retrieve data from npm. Please try again a little bit later.";
private versionsCache: IDictionary<string[]>;
constructor(private $npm: INodePackageManager,
private $logger: ILogger,
private $lockfile: ILockFile,
private $errors: IErrors,
private $options: IOptions,
private $fs: IFileSystem) {
this.versionsCache = {};
this.$npm.load().wait();
}
public getCacheRootPath(): string {
return this.$npm.getCache();
}
public getCachedPackagePath(packageName: string, version: string): string {
return path.join(this.getCacheRootPath(), packageName, version, "package");
}
public addToCache(packageName: string, version: string): IFuture<void> {
return (() => {
this.$npm.cache(packageName, version).wait();
let packagePath = path.join(this.getCacheRootPath(), packageName, version, "package");
if(!this.isPackageUnpacked(packagePath).wait()) {
this.cacheUnpack(packageName, version).wait();
}
}).future<void>()();
}
public cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void> {
unpackTarget = unpackTarget || path.join(npm.cache, packageName, version, "package");
return this.$npm.cacheUnpack(packageName, version, unpackTarget);
}
public getLatestVersion(packageName: string): IFuture<string> {
return (() => {
let data = this.$npm.view(packageName, "dist-tags").wait();
let latestVersion = _.first(_.keys(data));
this.$logger.trace("Using version %s. ", latestVersion);
return latestVersion;
}).future<string>()();
}
public install(packageName: string, opts?: INpmInstallOptions): IFuture<string> {
return (() => {
this.$lockfile.lock().wait();
try {
var packageToInstall = packageName;
var pathToSave = (opts && opts.pathToSave) || npm.cache;
var version = (opts && opts.version) || null;
return this.installCore(packageToInstall, pathToSave, version).wait();
} catch(error) {
this.$logger.debug(error);
this.$errors.fail("%s. Error: %s", NpmInstallationManager.NPM_LOAD_FAILED, error);
} finally {
this.$lockfile.unlock().wait();
}
}).future<string>()();
}
private installCore(packageName: string, pathToSave: string, version: string): IFuture<string> {
return (() => {
if (this.$options.frameworkPath) {
if (this.$fs.getFsStats(this.$options.frameworkPath).wait().isFile()) {
this.npmInstall(packageName, pathToSave, version).wait();
var pathToNodeModules = path.join(pathToSave, "node_modules");
var folders = this.$fs.readDirectory(pathToNodeModules).wait();
return path.join(pathToNodeModules, folders[0]);
}
return this.$options.frameworkPath;
} else {
version = version || this.getLatestVersion(packageName).wait();
var packagePath = this.getCachedPackagePath(packageName, version);
if (!this.isPackageCached(packagePath).wait()) {
this.$npm.cache(packageName, version).wait();
}
if(!this.isPackageUnpacked(packagePath).wait()) {
this.cacheUnpack(packageName, version).wait();
}
return packagePath;
}
}).future<string>()();
}
private npmInstall(packageName: string, pathToSave: string, version: string): IFuture<void> {
this.$logger.out("Installing ", packageName);
var incrementedVersion = semver.inc(version, constants.ReleaseType.MINOR);
if (!this.$options.frameworkPath && packageName.indexOf("@") < 0) {
packageName = packageName + "@<" + incrementedVersion;
}
return this.$npm.install(packageName, pathToSave);
}
private isPackageCached(packagePath: string): IFuture<boolean> {
return this.$fs.exists(packagePath);
}
private isPackageUnpacked(packagePath: string): IFuture<boolean> {
return (() => {
return this.$fs.getFsStats(packagePath).wait().isDirectory() &&
this.$fs.exists(path.join(packagePath, "framework")).wait() &&
this.$fs.enumerateFilesInDirectorySync(path.join(packagePath, "framework")).length > 1;
}).future<boolean>()();
}
}
$injector.register("npmInstallationManager", NpmInstallationManager);