Skip to content

Commit 6c50fb5

Browse files
committed
remove npm2 dependency
1 parent 098e876 commit 6c50fb5

24 files changed

+460
-645
lines changed

lib/commands/install.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export class InstallCommand implements ICommand {
5353
moduleName = devPrefix + moduleName;
5454
}
5555

56-
this.$npm.install(moduleName, projectDir, { 'save-dev': true }).wait();
56+
this.$npm.install(moduleName, projectDir, { 'save-dev': true });
5757
}).future<void>()();
5858
}
5959
}

lib/commands/test-init.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class TestInitCommand implements ICommand {
3434
this.$npm.install(mod, projectDir, {
3535
'save-dev': true,
3636
optional: false,
37-
}).wait();
37+
});
3838
});
3939

4040
this.$pluginsService.add('nativescript-unit-test-runner').wait();

lib/constants.ts

+21-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ export let TEST_RUNNER_NAME = "nativescript-unit-test-runner";
1616
export let LIVESYNC_EXCLUDED_FILE_PATTERNS = ["**/*.js.map", "**/*.ts"];
1717
export let XML_FILE_EXTENSION = ".xml";
1818

19+
export class PackageVersion {
20+
static NEXT = "next";
21+
static LATEST = "latest";
22+
}
23+
24+
export class SaveOptions {
25+
static PRODUCTION = "save"
26+
static DEV = "save-dev";
27+
static OPTIONAL = "save-optional"
28+
static EXACT = "save-exact"
29+
}
30+
1931
export class ReleaseType {
2032
static MAJOR = "major";
2133
static PREMAJOR = "premajor";
@@ -26,6 +38,14 @@ export class ReleaseType {
2638
static PRERELEASE = "prerelease";
2739
}
2840

41+
export let RESERVED_TEMPLATE_NAMES: IStringDictionary = {
42+
"default": "tns-template-hello-world",
43+
"tsc": "tns-template-hello-world-ts",
44+
"typescript": "tns-template-hello-world-ts",
45+
"ng": "tns-template-hello-world-ng",
46+
"angular": "tns-template-hello-world-ng"
47+
};
48+
2949
export class ITMSConstants {
3050
static ApplicationMetadataFile = "metadata.xml";
3151
static VerboseLoggingLevels = {
@@ -44,4 +64,4 @@ class ItunesConnectApplicationTypesClass implements IiTunesConnectApplicationTyp
4464
export let ItunesConnectApplicationTypes = new ItunesConnectApplicationTypesClass();
4565

4666
export let ANGULAR_NAME = "angular";
47-
export let TYPESCRIPT_NAME = "TypeScript";
67+
export let TYPESCRIPT_NAME = "typescript";

lib/declarations.ts

+7-14
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
11
interface INodePackageManager {
2-
getCache(): string;
3-
load(config?: any): IFuture<void>;
4-
install(packageName: string, pathToSave: string, config?: any): IFuture<any>;
2+
install(packageName: string, pathToSave: string, config?: any): any;
53
uninstall(packageName: string, config?: any, path?: string): IFuture<any>;
6-
cache(packageName: string, version: string, cache?: any): IFuture<IDependencyData>;
7-
cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void>;
8-
view(packageName: string, propertyName: string): IFuture<any>;
9-
executeNpmCommand(npmCommandName: string, currentWorkingDirectory: string): IFuture<any>;
4+
view(packageName: string, config: any): any;
105
search(filter: string[], silent: boolean): IFuture<any>;
116
}
127

138
interface INpmInstallationManager {
14-
getCacheRootPath(): string;
15-
addToCache(packageName: string, version: string): IFuture<any>;
16-
cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void>;
17-
install(packageName: string, options?: INpmInstallOptions): IFuture<string>;
9+
install(packageName: string, packageDir: string, options?: INpmInstallOptions): IFuture<any>;
1810
getLatestVersion(packageName: string): IFuture<string>;
11+
getNextVersion(packageName: string): IFuture<string>;
1912
getLatestCompatibleVersion(packageName: string): IFuture<string>;
20-
getCachedPackagePath(packageName: string, version: string): string;
2113
}
2214

2315
interface INpmInstallOptions {
2416
pathToSave?: string;
2517
version?: string;
18+
dependencyType?: string;
2619
}
2720

2821
interface IDependencyData {
@@ -81,7 +74,7 @@ interface IOptions extends ICommonOptions {
8174
frameworkName: string;
8275
frameworkPath: string;
8376
frameworkVersion: string;
84-
ignoreScripts: boolean;
77+
ignoreScripts: boolean; //npm flag
8578
disableNpmInstall: boolean;
8679
ipa: string;
8780
keyStoreAlias: string;
@@ -94,7 +87,7 @@ interface IOptions extends ICommonOptions {
9487
bundle: boolean;
9588
platformTemplate: string;
9689
port: Number;
97-
production: boolean;
90+
production: boolean; //npm flag
9891
sdk: string;
9992
symlink: boolean;
10093
tnsModulesVersion: string;

lib/definitions/project.d.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ interface IProjectDataService {
2626
* Describes working with templates.
2727
*/
2828
interface IProjectTemplatesService {
29-
/**
30-
* Defines the path where unpacked default template can be found.
31-
*/
32-
defaultTemplatePath: IFuture<string>;
33-
3429
/**
3530
* Prepares template for project creation.
3631
* In case templateName is not provided, use defaultTemplatePath.
@@ -39,7 +34,7 @@ interface IProjectTemplatesService {
3934
* @param {string} templateName The name of the template.
4035
* @return {string} Path to the directory where extracted template can be found.
4136
*/
42-
prepareTemplate(templateName: string): IFuture<string>;
37+
prepareTemplate(templateName: string, projectDir: string): IFuture<string>;
4338
}
4439

4540
interface IPlatformProjectServiceBase {
@@ -77,12 +72,12 @@ interface IPlatformProjectService {
7772
prepareProject(): IFuture<void>;
7873
prepareAppResources(appResourcesDirectoryPath: string): IFuture<void>;
7974
isPlatformPrepared(projectRoot: string): IFuture<boolean>;
80-
canUpdatePlatform(currentVersion: string, newVersion: string): IFuture<boolean>;
75+
canUpdatePlatform(newInstalledModuleDir: string): IFuture<boolean>;
8176
/**
8277
* Provides a platform specific update logic for the specified runtime versions.
8378
* @return true in cases when the update procedure should continue.
8479
*/
85-
updatePlatform(currentVersion: string, newVersion: string, canUpdate: boolean, addPlatform?: Function, removePlatform?: (platforms: string[]) => IFuture<void>): IFuture<boolean>;
80+
// updatePlatform(currentVersion: string, newVersion: string, canUpdate: boolean, addPlatform?: Function, removePlatform?: (platforms: string[]) => IFuture<void>): IFuture<boolean>;
8681
preparePluginNativeCode(pluginData: IPluginData, options?: any): IFuture<void>;
8782
removePluginNativeCode(pluginData: IPluginData): IFuture<void>;
8883
afterPrepareAllPlugins(): IFuture<void>;

lib/node-package-manager.ts

+74-115
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import Future = require("fibers/future");
2-
import * as npm from "npm";
1+
import * as path from "path";
32

43
interface INpmOpts {
54
config?: any;
@@ -8,139 +7,99 @@ interface INpmOpts {
87
}
98

109
export class NodePackageManager implements INodePackageManager {
11-
constructor(private $childProcess: IChildProcess,
10+
constructor(private $fs: IFileSystem,
11+
private $errors: IErrors,
12+
private $childProcess: IChildProcess,
1213
private $logger: ILogger,
1314
private $options: IOptions) { }
1415

15-
public getCache(): string {
16-
return npm.cache;
17-
}
18-
19-
public load(config?: any): IFuture<void> {
20-
if (npm.config.loaded) {
21-
let data = npm.config.sources.cli.data;
22-
Object.keys(data).forEach(k => delete data[k]);
23-
if (config) {
24-
_.assign(data, config);
25-
}
26-
return Future.fromResult();
27-
} else {
28-
let future = new Future<void>();
29-
npm.load(config, (err: Error) => {
30-
if (err) {
31-
future.throw(err);
32-
} else {
33-
future.return();
34-
}
35-
});
36-
return future;
16+
public install(packageName: string, pathToSave: string, config?: any): any {
17+
if (this.$options.disableNpmInstall) {
18+
return;
19+
}
20+
if (this.$options.ignoreScripts) {
21+
config = config || {};
22+
config["ignore-scripts"] = true;
3723
}
38-
}
3924

40-
public install(packageName: string, pathToSave: string, config?: any): IFuture<any> {
41-
return (() => {
42-
if (this.$options.disableNpmInstall) {
43-
return;
44-
}
45-
if (this.$options.ignoreScripts) {
46-
config = config || {};
47-
config["ignore-scripts"] = true;
25+
try {
26+
let subDirsBefore:Array<string> = this.$fs.exists(path.join(pathToSave, "node_modules")).wait() ? this.$fs.readDirectory(path.join(pathToSave, "node_modules")).wait() : [];
27+
28+
let flags = this.getFlagsString(config);
29+
this.$childProcess.exec(`npm install ${packageName} ${flags}`, { cwd: pathToSave }).wait();
30+
31+
let subDirsAfter = this.$fs.readDirectory(path.join(pathToSave, "node_modules")).wait();
32+
33+
/** This diff is done in case the installed pakcage is a URL address, a path to local directory or a .tgz file
34+
* in these cases we don't have the package name and we can't rely on "npm install --json"" option
35+
* to get the project name because we have to parse the output from the stdout and we have no controll over it (so other messages may be mangled in stdout)
36+
* The solution is to traverse node_modules before and after install and get the name of the installed package,
37+
* even if it's installed through local path or URL. If command installes more than one package, all package names are returned.
38+
*/
39+
let diff = subDirsAfter.filter(x => subDirsBefore.indexOf(x) == -1);
40+
if(diff.length <= 0 && subDirsBefore.length != subDirsAfter.length) {
41+
this.$errors.failWithoutHelp(`Couldn't install package correctly`);
4842
}
4943

50-
try {
51-
return this.loadAndExecute("install", [pathToSave, packageName], { config: config }).wait();
52-
} catch (err) {
53-
if (err.code === "EPEERINVALID") {
54-
// Not installed peer dependencies are treated by npm 2 as errors, but npm 3 treats them as warnings.
55-
// We'll show them as warnings and let the user install them in case they are needed.
56-
// The strucutre of the error object in such case is:
57-
// { [Error: The package @angular/[email protected] does not satisfy its siblings' peerDependencies requirements!]
58-
// code: 'EPEERINVALID',
59-
// packageName: '@angular/core',
60-
// packageVersion: '2.1.0-beta.0',
61-
// peersDepending:
62-
// { '@angular/[email protected]': '2.1.0-beta.0',
63-
// '@angular/[email protected]': '2.1.0-beta.0',
64-
// '@angular/[email protected]': '2.1.0-beta.0',
65-
// '@angular/[email protected]': '2.1.0-beta.0',
66-
// '@angular/[email protected]': '2.1.0-beta.0',
67-
// '@angular/[email protected]': '2.1.0-beta.0',
68-
// '@angular/[email protected]': '2.1.0-beta.0',
69-
// '@angular/[email protected]': '2.1.0-beta.0',
70-
// '@ngrx/[email protected]': '^2.0.0',
71-
// '@ngrx/[email protected]': '^2.0.0',
72-
// '[email protected]': '~2.0.0' } }
73-
this.$logger.warn(err.message);
74-
this.$logger.trace("Required peerDependencies are: ", err.peersDepending);
75-
} else {
76-
// All other errors should be handled by the caller code.
77-
throw err;
78-
}
44+
return diff;
45+
} catch (err) {
46+
if (err.code === "EPEERINVALID") {
47+
// Not installed peer dependencies are treated by npm 2 as errors, but npm 3 treats them as warnings.
48+
// We'll show them as warnings and let the user install them in case they are needed.
49+
// The strucutre of the error object in such case is:
50+
// { [Error: The package @angular/[email protected] does not satisfy its siblings' peerDependencies requirements!]
51+
// code: 'EPEERINVALID',
52+
// packageName: '@angular/core',
53+
// packageVersion: '2.1.0-beta.0',
54+
// peersDepending:
55+
// { '@angular/[email protected]': '2.1.0-beta.0',
56+
// '@angular/[email protected]': '2.1.0-beta.0',
57+
// '@angular/[email protected]': '2.1.0-beta.0',
58+
// '@angular/[email protected]': '2.1.0-beta.0',
59+
// '@angular/[email protected]': '2.1.0-beta.0',
60+
// '@angular/[email protected]': '2.1.0-beta.0',
61+
// '@angular/[email protected]': '2.1.0-beta.0',
62+
// '@angular/[email protected]': '2.1.0-beta.0',
63+
// '@ngrx/[email protected]': '^2.0.0',
64+
// '@ngrx/[email protected]': '^2.0.0',
65+
// '[email protected]': '~2.0.0' } }
66+
this.$logger.warn(err.message);
67+
this.$logger.trace("Required peerDependencies are: ", err.peersDepending);
68+
} else {
69+
// All other errors should be handled by the caller code.
70+
throw err;
7971
}
80-
}).future<any>()();
72+
}
8173
}
82-
74+
8375
public uninstall(packageName: string, config?: any, path?: string): IFuture<any> {
84-
return this.loadAndExecute("uninstall", [[packageName]], { config, path });
76+
let flags = this.getFlagsString(config);
77+
return this.$childProcess.exec(`npm uninstall ${packageName} ${flags}`, { cwd: path });
8578
}
8679

8780
public search(filter: string[], silent: boolean): IFuture<any> {
8881
let args = (<any[]>([filter] || [])).concat(silent);
89-
return this.loadAndExecute("search", args);
82+
return this.$childProcess.exec(`npm search ${args}`);
9083
}
9184

92-
public cache(packageName: string, version: string, config?: any): IFuture<IDependencyData> {
93-
// function cache (pkg, ver, where, scrub, cb)
94-
return this.loadAndExecute("cache", [packageName, version, undefined, false], { subCommandName: "add", config: config });
85+
public view(packageName: string, config: any): IFuture<any> {
86+
let flags = this.getFlagsString(config);
87+
let viewResult = this.$childProcess.exec(`npm view ${packageName} ${flags}`).wait();
88+
return JSON.parse(viewResult);
9589
}
9690

97-
public cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void> {
98-
// function unpack (pkg, ver, unpackTarget, dMode, fMode, uid, gid, cb)
99-
return this.loadAndExecute("cache", [packageName, version, unpackTarget, null, null, null, null], { subCommandName: "unpack" });
100-
}
101-
102-
public view(packageName: string, propertyName: string): IFuture<any> {
103-
return this.loadAndExecute("view", [[packageName, propertyName], [false]]);
104-
}
105-
106-
public executeNpmCommand(npmCommandName: string, currentWorkingDirectory: string): IFuture<any> {
107-
return this.$childProcess.exec(npmCommandName, { cwd: currentWorkingDirectory });
108-
}
109-
110-
private loadAndExecute(commandName: string, args: any[], opts?: INpmOpts): IFuture<any> {
111-
return (() => {
112-
opts = opts || {};
113-
this.load(opts.config).wait();
114-
return this.executeCore(commandName, args, opts).wait();
115-
}).future<any>()();
116-
}
117-
118-
private executeCore(commandName: string, args: any[], opts?: INpmOpts): IFuture<any> {
119-
let future = new Future<any>();
120-
let oldNpmPath: string = undefined;
121-
let callback = (err: Error, data: any) => {
122-
if (oldNpmPath) {
123-
npm.prefix = oldNpmPath;
124-
}
125-
126-
if (err) {
127-
future.throw(err);
128-
} else {
129-
future.return(data);
91+
private getFlagsString(config: any) : string{
92+
let flagsString = "";
93+
for(let flag in config) {
94+
if(config[flag]) {
95+
if(flag==="dist-tags" || flag==="versions") {
96+
flagsString += ` ${flag}`;
97+
continue;
98+
}
99+
flagsString += ` --${flag}`;
130100
}
131-
};
132-
args.push(callback);
133-
134-
if (opts && opts.path) {
135-
oldNpmPath = npm.prefix;
136-
npm.prefix = opts.path;
137101
}
138-
139-
let subCommandName: string = opts.subCommandName;
140-
let command = subCommandName ? npm.commands[commandName][subCommandName] : npm.commands[commandName];
141-
command.apply(this, args);
142-
143-
return future;
102+
return flagsString;
144103
}
145104
}
146105
$injector.register("npm", NodePackageManager);

0 commit comments

Comments
 (0)