-
-
Notifications
You must be signed in to change notification settings - Fork 197
/
Copy pathnode-package-manager.ts
146 lines (128 loc) · 4.81 KB
/
node-package-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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import Future = require("fibers/future");
import * as npm from "npm";
interface INpmOpts {
config?: any;
subCommandName?: string;
path?: string;
}
export class NodePackageManager implements INodePackageManager {
constructor(private $childProcess: IChildProcess,
private $logger: ILogger,
private $options: IOptions) { }
public getCache(): string {
return npm.cache;
}
public load(config?: any): IFuture<void> {
if (npm.config.loaded) {
let data = npm.config.sources.cli.data;
Object.keys(data).forEach(k => delete data[k]);
if (config) {
_.assign(data, config);
}
return Future.fromResult();
} else {
let future = new Future<void>();
npm.load(config, (err: Error) => {
if (err) {
future.throw(err);
} else {
future.return();
}
});
return future;
}
}
public install(packageName: string, pathToSave: string, config?: any): IFuture<any> {
return (() => {
if (this.$options.disableNpmInstall) {
return;
}
if (this.$options.ignoreScripts) {
config = config || {};
config["ignore-scripts"] = true;
}
try {
return this.loadAndExecute("install", [pathToSave, packageName], { config: config }).wait();
} catch (err) {
if (err.code === "EPEERINVALID") {
// Not installed peer dependencies are treated by npm 2 as errors, but npm 3 treats them as warnings.
// We'll show them as warnings and let the user install them in case they are needed.
// The strucutre of the error object in such case is:
// { [Error: The package @angular/[email protected] does not satisfy its siblings' peerDependencies requirements!]
// code: 'EPEERINVALID',
// packageName: '@angular/core',
// packageVersion: '2.1.0-beta.0',
// peersDepending:
// { '@angular/[email protected]': '2.1.0-beta.0',
// '@angular/[email protected]': '2.1.0-beta.0',
// '@angular/[email protected]': '2.1.0-beta.0',
// '@angular/[email protected]': '2.1.0-beta.0',
// '@angular/[email protected]': '2.1.0-beta.0',
// '@angular/[email protected]': '2.1.0-beta.0',
// '@angular/[email protected]': '2.1.0-beta.0',
// '@angular/[email protected]': '2.1.0-beta.0',
// '@ngrx/[email protected]': '^2.0.0',
// '@ngrx/[email protected]': '^2.0.0',
// '[email protected]': '~2.0.0' } }
this.$logger.warn(err.message);
this.$logger.trace("Required peerDependencies are: ", err.peersDepending);
} else {
// All other errors should be handled by the caller code.
throw err;
}
}
}).future<any>()();
}
public uninstall(packageName: string, config?: any, path?: string): IFuture<any> {
return this.loadAndExecute("uninstall", [[packageName]], { config, path });
}
public search(filter: string[], silent: boolean): IFuture<any> {
let args = (<any[]>([filter] || [])).concat(silent);
return this.loadAndExecute("search", args);
}
public cache(packageName: string, version: string, config?: any): IFuture<IDependencyData> {
// function cache (pkg, ver, where, scrub, cb)
return this.loadAndExecute("cache", [packageName, version, undefined, false], { subCommandName: "add", config: config });
}
public cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void> {
// function unpack (pkg, ver, unpackTarget, dMode, fMode, uid, gid, cb)
return this.loadAndExecute("cache", [packageName, version, unpackTarget, null, null, null, null], { subCommandName: "unpack" });
}
public view(packageName: string, propertyName: string): IFuture<any> {
return this.loadAndExecute("view", [[packageName, propertyName], [false]]);
}
public executeNpmCommand(npmCommandName: string, currentWorkingDirectory: string): IFuture<any> {
return this.$childProcess.exec(npmCommandName, { cwd: currentWorkingDirectory });
}
private loadAndExecute(commandName: string, args: any[], opts?: INpmOpts): IFuture<any> {
return (() => {
opts = opts || {};
this.load(opts.config).wait();
return this.executeCore(commandName, args, opts).wait();
}).future<any>()();
}
private executeCore(commandName: string, args: any[], opts?: INpmOpts): IFuture<any> {
let future = new Future<any>();
let oldNpmPath: string = undefined;
let callback = (err: Error, data: any) => {
if (oldNpmPath) {
(<any>npm).prefix = oldNpmPath;
}
if (err) {
future.throw(err);
} else {
future.return(data);
}
};
args.push(callback);
if (opts && opts.path) {
oldNpmPath = npm.prefix;
(<any>npm).prefix = opts.path;
}
let subCommandName: string = opts.subCommandName;
let command = subCommandName ? npm.commands[commandName][subCommandName] : npm.commands[commandName];
command.apply(this, args);
return future;
}
}
$injector.register("npm", NodePackageManager);