Skip to content

Commit e64054a

Browse files
committed
Use npm api instead exec
1 parent 00e8b32 commit e64054a

15 files changed

+307
-242
lines changed

lib/bootstrap.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ $injector.requireCommand("emulate|android", "./commands/emulate");
4444
$injector.requireCommand("emulate|ios", "./commands/emulate");
4545

4646
$injector.require("npm", "./node-package-manager");
47+
$injector.require("npmInstallationManager", "./npm-installation-manager");
4748
$injector.require("lockfile", "./lockfile");
4849
$injector.require("dynamicHelpProvider", "./dynamic-help-provider");
4950
$injector.require("mobilePlatformsCapabilities", "./mobile-platforms-capabilities");

lib/declarations.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
interface INodePackageManager {
2+
getCache(): string;
3+
load(config?: any): IFuture<void>;
4+
install(packageName: string, pathToSave: string, config?: any): IFuture<any>;
5+
uninstall(packageName: string, config?: any): IFuture<any>;
6+
cache(packageName: string, version: string, cache?: any): IFuture<ICacheData>;
7+
cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void>;
8+
view(packageName: string, propertyName: string): IFuture<any>;
9+
}
10+
11+
interface INpmInstallationManager {
212
getCacheRootPath(): string;
313
addToCache(packageName: string, version: string): IFuture<void>;
414
cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void>;
5-
load(config?: any): IFuture<void>;
615
install(packageName: string, options?: INpmInstallOptions): IFuture<string>;
716
getLatestVersion(packageName: string): IFuture<string>;
817
getCachedPackagePath(packageName: string, version: string): string;
@@ -13,6 +22,14 @@ interface INpmInstallOptions {
1322
version?: string;
1423
}
1524

25+
interface ICacheData {
26+
name: string;
27+
version: string;
28+
dependencies: IStringDictionary;
29+
devDependencies: IStringDictionary;
30+
nativescript?: any;
31+
}
32+
1633
interface IStaticConfig extends Config.IStaticConfig { }
1734

1835
interface IConfiguration extends Config.IConfig { }
@@ -39,7 +56,7 @@ interface IOptions extends ICommonOptions {
3956
emulator: boolean;
4057
symlink: boolean;
4158
forDevice: boolean;
42-
client: boolean
59+
client: boolean;
4360
production: boolean;
4461
keyStorePath: string;
4562
keyStorePassword: string;

lib/node-package-manager.ts

Lines changed: 36 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,18 @@
33

44
import Future = require("fibers/future");
55
import npm = require("npm");
6-
import path = require("path");
7-
import semver = require("semver");
8-
import shell = require("shelljs");
9-
import helpers = require("./common/helpers");
10-
import constants = require("./constants");
116

127
export class NodePackageManager implements INodePackageManager {
13-
private static NPM_LOAD_FAILED = "Failed to retrieve data from npm. Please try again a little bit later.";
14-
private static NPM_REGISTRY_URL = "http://registry.npmjs.org/";
15-
16-
private versionsCache: IDictionary<string[]>;
17-
188
constructor(private $logger: ILogger,
199
private $errors: IErrors,
2010
private $fs: IFileSystem,
2111
private $lockfile: ILockFile,
22-
private $options: IOptions) {
23-
this.versionsCache = {};
24-
this.load().wait();
25-
}
12+
private $options: IOptions) { }
2613

27-
public getCacheRootPath(): string {
14+
public getCache(): string {
2815
return npm.cache;
2916
}
30-
31-
public addToCache(packageName: string, version: string): IFuture<void> {
32-
return (() => {
33-
this.addToCacheCore(packageName, version).wait();
34-
35-
var packagePath = path.join(npm.cache, packageName, version, "package");
36-
if(!this.isPackageUnpacked(packagePath).wait()) {
37-
this.cacheUnpack(packageName, version).wait();
38-
}
39-
}).future<void>()();
40-
}
41-
17+
4218
public load(config?: any): IFuture<void> {
4319
var future = new Future<void>();
4420
npm.load(config, (err) => {
@@ -50,128 +26,51 @@ export class NodePackageManager implements INodePackageManager {
5026
});
5127
return future;
5228
}
53-
54-
public install(packageName: string, opts?: INpmInstallOptions): IFuture<string> {
55-
return (() => {
56-
this.$lockfile.lock().wait();
57-
58-
try {
59-
var packageToInstall = packageName;
60-
var pathToSave = (opts && opts.pathToSave) || npm.cache;
61-
var version = (opts && opts.version) || null;
62-
63-
return this.installCore(packageToInstall, pathToSave, version).wait();
64-
} catch(error) {
65-
this.$logger.debug(error);
66-
this.$errors.fail("%s. Error: %s", NodePackageManager.NPM_LOAD_FAILED, error);
67-
} finally {
68-
this.$lockfile.unlock().wait();
69-
}
70-
71-
}).future<string>()();
29+
30+
public install(packageName: string, pathToSave: string, config?: any): IFuture<any> {
31+
return this.loadAndExecute("install", [pathToSave, packageName], { config: config });
7232
}
73-
74-
public getLatestVersion(packageName: string): IFuture<string> {
75-
var future = new Future<string>();
76-
77-
npm.commands["view"]([packageName, "dist-tags"], [false], (err: any, data: any) => { // [false] - silent
78-
if(err) {
79-
future.throw(err);
80-
} else {
81-
var latestVersion = _.first(_.keys(data));
82-
this.$logger.trace("Using version %s. ", latestVersion);
83-
84-
future.return(latestVersion);
85-
}
86-
});
87-
88-
return future;
33+
34+
public uninstall(packageName: string, config?: any): IFuture<any> {
35+
return this.loadAndExecute("uninstall", [[packageName]], { config: config });
8936
}
9037

91-
public getCachedPackagePath(packageName: string, version: string): string {
92-
return path.join(npm.cache, packageName, version, "package");
38+
public cache(packageName: string, version: string, config?: any): IFuture<ICacheData> {
39+
// function cache (pkg, ver, where, scrub, cb)
40+
return this.loadAndExecute("cache", [packageName, version, undefined, false], { subCommandName: "add", config: config });
9341
}
94-
95-
private installCore(packageName: string, pathToSave: string, version: string): IFuture<string> {
96-
return (() => {
97-
if (this.$options.frameworkPath) {
98-
if (this.$fs.getFsStats(this.$options.frameworkPath).wait().isFile()) {
99-
this.npmInstall(packageName, pathToSave, version).wait();
100-
var pathToNodeModules = path.join(pathToSave, "node_modules");
101-
var folders = this.$fs.readDirectory(pathToNodeModules).wait();
102-
return path.join(pathToNodeModules, folders[0]);
103-
}
104-
return this.$options.frameworkPath;
105-
} else {
106-
version = version || this.getLatestVersion(packageName).wait();
107-
var packagePath = this.getCachedPackagePath(packageName, version);
108-
if (!this.isPackageCached(packagePath).wait()) {
109-
this.addToCacheCore(packageName, version).wait();
110-
}
111-
112-
if(!this.isPackageUnpacked(packagePath).wait()) {
113-
this.cacheUnpack(packageName, version).wait();
114-
}
115-
return packagePath;
116-
}
117-
}).future<string>()();
118-
}
119-
120-
private npmInstall(packageName: string, pathToSave: string, version: string): IFuture<void> {
121-
this.$logger.out("Installing ", packageName);
122-
123-
var incrementedVersion = semver.inc(version, constants.ReleaseType.MINOR);
124-
if (!this.$options.frameworkPath && packageName.indexOf("@") < 0) {
125-
packageName = packageName + "@<" + incrementedVersion;
126-
}
127-
128-
var future = new Future<void>();
129-
npm.commands["install"](pathToSave, packageName, (err: Error, data: any) => {
130-
if(err) {
131-
future.throw(err);
132-
} else {
133-
this.$logger.out("Installed ", packageName);
134-
future.return(data);
135-
}
136-
});
137-
return future;
42+
43+
public cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void> {
44+
// function unpack (pkg, ver, unpackTarget, dMode, fMode, uid, gid, cb)
45+
return this.loadAndExecute("cache", [packageName, version, unpackTarget, null, null, null, null], { subCommandName: "unpack" });
13846
}
139-
140-
private isPackageCached(packagePath: string): IFuture<boolean> {
141-
return this.$fs.exists(packagePath);
47+
48+
public view(packageName: string, propertyName: string): IFuture<any> {
49+
return this.loadAndExecute("view", [[packageName, propertyName], [false]]);
14250
}
143-
144-
private isPackageUnpacked(packagePath: string): IFuture<boolean> {
51+
52+
private loadAndExecute(commandName: string, args: any[], opts?: { config?: any, subCommandName?: string }): IFuture<any> {
14553
return (() => {
146-
return this.$fs.getFsStats(packagePath).wait().isDirectory() &&
147-
this.$fs.enumerateFilesInDirectorySync(packagePath).length > 1;
148-
}).future<boolean>()();
149-
}
150-
151-
private addToCacheCore(packageName: string, version: string): IFuture<void> {
152-
var future = new Future<void>();
153-
// cache.add = function (pkg, ver, where, scrub, cb)
154-
npm.commands["cache"].add(packageName, version, undefined, false, (err: Error, data: any) => {
155-
if(err) {
156-
future.throw(err);
157-
} else {
158-
future.return();
159-
}
160-
});
161-
return future;
54+
opts = opts || {};
55+
this.load(opts.config).wait();
56+
return this.executeCore(commandName, args, opts.subCommandName).wait();
57+
}).future<any>()();
16258
}
163-
164-
public cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void> {
165-
var future = new Future<void>();
166-
unpackTarget = unpackTarget || path.join(npm.cache, packageName, version, "package");
167-
// function unpack (pkg, ver, unpackTarget, dMode, fMode, uid, gid, cb)
168-
npm.commands["cache"].unpack(packageName, version, unpackTarget, null, null, null, null, (err: Error, data: any) => {
59+
60+
private executeCore(commandName: string, args: any[], subCommandName?: string): IFuture<any> {
61+
let future = new Future<any>();
62+
let callback = (err: Error, data: any) => {
16963
if(err) {
17064
future.throw(err);
17165
} else {
172-
future.return();
66+
future.return(data);
17367
}
174-
});
68+
}
69+
args.push(callback);
70+
71+
let command = subCommandName ? npm.commands[commandName][subCommandName] : npm.commands[commandName];
72+
command.apply(this, args);
73+
17574
return future;
17675
}
17776
}

lib/npm-installation-manager.ts

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

0 commit comments

Comments
 (0)