Skip to content

Commit a81778d

Browse files
committed
Merge pull request #10 from NativeScript/fatme/ios
Create, prepare and build commands for iOS
2 parents c916ae6 + d534ce0 commit a81778d

13 files changed

+307
-149
lines changed

.idea/nativescript-cli.iml

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/constants.ts

+11
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,14 @@ export var DEFAULT_PROJECT_NAME = "HelloNativescript";
66
export var APP_RESOURCES_FOLDER_NAME = "App_Resources";
77
export var PROJECT_FRAMEWORK_FOLDER_NAME = "framework";
88

9+
export class ReleaseType {
10+
static MAJOR = "major";
11+
static PREMAJOR = "premajor";
12+
static MINOR = "minor";
13+
static PREMINOR = "preminor";
14+
static PATCH = "patch";
15+
static PREPATCH = "prepatch";
16+
static PRERELEASE = "prerelease";
17+
}
18+
19+

lib/declarations.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
interface INodePackageManager {
22
cache: string;
33
load(config?: any): IFuture<void>;
4-
install(packageName: string, pathToSave?: string): IFuture<string>;
4+
install(packageName: string, pathToSave?: string, version?: string): IFuture<string>;
55
}
66

7-
interface IStaticConfig extends Config.IStaticConfig { }
7+
interface IStaticConfig extends Config.IStaticConfig { }
8+

lib/definitions/project.d.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ interface IProjectTemplatesService {
1515
}
1616

1717
interface IPlatformProjectService {
18+
platformData: IPlatformData;
1819
validate(): IFuture<void>;
1920
createProject(projectRoot: string, frameworkDir: string): IFuture<void>;
20-
interpolateData(projectRoot: string): void;
21-
afterCreateProject(projectRoot: string): void;
22-
prepareProject(normalizedPlatformName: string, platforms: string[]): IFuture<void>;
21+
interpolateData(projectRoot: string): IFuture<void>;
22+
afterCreateProject(projectRoot: string): IFuture<void>;
23+
prepareProject(platformData: IPlatformData): IFuture<string>;
2324
buildProject(projectRoot: string): IFuture<void>;
2425
}

lib/definitions/semver.d.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
declare module "semver" {
3+
function gt(version1: string, version2: string): boolean;
4+
function lt(version1: string, version2: string): boolean;
5+
function valid(version: string): boolean;
6+
function inc(version: string, release: string): string;
7+
function inc(version: string, release: "major"): string;
8+
function inc(version: string, release: 'premajor'): string;
9+
function inc(version: string, release: 'minor'): string;
10+
function inc(version: string, release: 'preminor'): string;
11+
function inc(version: string, release: 'patch'): string;
12+
function inc(version: string, release: 'prepatch'): string;
13+
function inc(version: string, release: 'prerelease'): string;
14+
}

lib/nativescript-cli.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ errors.installUncaughtExceptionListener();
1212

1313
$injector.register("config", {
1414
CI_LOGGER: false,
15-
DEBUG: process.env.NATIVESCRIPT_DEBUG
15+
PROJECT_FILE_NAME: ".tnsproject",
16+
DEBUG: process.env.NATIVESCRIPT_DEBUG,
17+
version: require("../package.json").version,
18+
helpTextPath: path.join(__dirname, "../resources/help.txt"),
19+
client: "tns"
1620
});
1721

1822
var dispatcher = $injector.resolve("dispatcher");

lib/node-package-manager.ts

+48-18
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
///<reference path=".d.ts"/>
22

3-
import npm = require("npm");
43
import Future = require("fibers/future");
5-
import shell = require("shelljs");
4+
import npm = require("npm");
65
import path = require("path");
6+
import semver = require("semver");
7+
import shell = require("shelljs");
8+
import helpers = require("./common/helpers");
9+
import constants = require("./constants");
710

811
export class NodePackageManager implements INodePackageManager {
912
private static NPM_LOAD_FAILED = "Failed to retrieve data from npm. Please try again a little bit later.";
13+
private static NPM_REGISTRY_URL = "http://registry.npmjs.org/";
1014

1115
constructor(private $logger: ILogger,
12-
private $errors: IErrors) { }
16+
private $errors: IErrors,
17+
private $httpClient: Server.IHttpClient,
18+
private $staticConfig: IStaticConfig) { }
1319

1420
public get cache(): string {
1521
return npm.cache;
@@ -27,23 +33,41 @@ export class NodePackageManager implements INodePackageManager {
2733
return future;
2834
}
2935

30-
public install(packageName: string, pathToSave?: string): IFuture<string> {
36+
public install(packageName: string, pathToSave?: string, version?: string): IFuture<string> {
3137
return (() => {
32-
var action = (packageName: string) => {
38+
try {
39+
this.load().wait(); // It's obligatory to execute load before whatever npm function
3340
pathToSave = pathToSave || npm.cache;
34-
this.installCore(pathToSave, packageName).wait();
35-
};
41+
var packageToInstall = packageName;
3642

37-
this.tryExecuteAction(action, packageName).wait();
43+
if(version) {
44+
this.validateVersion(packageName, version).wait();
45+
packageToInstall = packageName + "@" + version;
46+
}
47+
48+
this.installCore(pathToSave, packageToInstall).wait();
49+
} catch(error) {
50+
this.$logger.debug(error);
51+
this.$errors.fail(NodePackageManager.NPM_LOAD_FAILED);
52+
}
3853

3954
return path.join(pathToSave, "node_modules", packageName);
4055

4156
}).future<string>()();
4257
}
4358

44-
private installCore(where: string, what: string): IFuture<any> {
45-
var future = new Future<any>();
46-
npm.commands["install"](where, what, (err, data) => {
59+
private installCore(packageName: string, pathToSave: string): IFuture<void> {
60+
var currentVersion = this.$staticConfig.version;
61+
if(!semver.valid(currentVersion)) {
62+
this.$errors.fail("Invalid version.");
63+
}
64+
65+
var incrementedVersion = semver.inc(currentVersion, constants.ReleaseType.MINOR);
66+
packageName = packageName + "@" + "<" + incrementedVersion;
67+
this.$logger.trace("Installing", packageName);
68+
69+
var future = new Future<void>();
70+
npm.commands["install"](pathToSave, packageName, (err, data) => {
4771
if(err) {
4872
future.throw(err);
4973
} else {
@@ -53,14 +77,20 @@ export class NodePackageManager implements INodePackageManager {
5377
return future;
5478
}
5579

56-
private tryExecuteAction(action: (...args: any[]) => void, ...args: any[]): IFuture<void> {
80+
private getAvailableVersions(packageName: string): IFuture<string[]> {
5781
return (() => {
58-
try {
59-
this.load().wait(); // It's obligatory to execute load before whatever npm function
60-
action.apply(null, args);
61-
} catch(error) {
62-
this.$logger.debug(error);
63-
this.$errors.fail(NodePackageManager.NPM_LOAD_FAILED);
82+
var url = NodePackageManager.NPM_REGISTRY_URL + packageName;
83+
var response = this.$httpClient.httpRequest(url).wait().body;
84+
var json = JSON.parse(response);
85+
return _.keys(json.versions);
86+
}).future<string[]>()();
87+
}
88+
89+
private validateVersion(packageName: string, version: string): IFuture<void> {
90+
return (() => {
91+
var versions = this.getAvailableVersions(packageName).wait();
92+
if(!_.contains(versions, version)) {
93+
this.$errors.fail("Invalid version. Valid versions are: %s", helpers.formatListOfNames(versions, "and"));
6494
}
6595
}).future<void>()();
6696
}

lib/options.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var knownOpts:any = {
1212
"copy-from": String,
1313
"link-to": String,
1414
"release": String,
15+
"device": Boolean,
1516
"version": Boolean,
1617
"help": Boolean
1718
},

lib/services/android-project-service.ts

+31-39
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ class AndroidProjectService implements IPlatformProjectService {
1616
private $projectData: IProjectData,
1717
private $propertiesParser: IPropertiesParser) { }
1818

19+
public get platformData(): IPlatformData {
20+
return {
21+
frameworkPackageName: "tns-android",
22+
normalizedPlatformName: "Android",
23+
platformProjectService: this,
24+
projectRoot: path.join(this.$projectData.platformsDir, "android")
25+
};
26+
}
27+
1928
public validate(): IFuture<void> {
2029
return (() => {
2130
this.validatePackageName(this.$projectData.projectId);
@@ -61,54 +70,49 @@ class AndroidProjectService implements IPlatformProjectService {
6170
}).future<void>()();
6271
}
6372

64-
public afterCreateProject(projectRoot: string) {
65-
var targetApi = this.getTarget(projectRoot).wait();
66-
this.$logger.trace("Android target: %s", targetApi);
67-
this.runAndroidUpdate(projectRoot, targetApi).wait();
73+
public afterCreateProject(projectRoot: string): IFuture<void> {
74+
return (() => {
75+
var targetApi = this.getTarget(projectRoot).wait();
76+
this.$logger.trace("Android target: %s", targetApi);
77+
this.runAndroidUpdate(projectRoot, targetApi).wait();
78+
}).future<void>()();
6879
}
6980

70-
public prepareProject(normalizedPlatformName: string, platforms: string[]): IFuture<void> {
81+
public prepareProject(platformData: IPlatformData): IFuture<string> {
7182
return (() => {
72-
var platform = normalizedPlatformName.toLowerCase();
73-
var assetsDirectoryPath = path.join(this.$projectData.platformsDir, platform, "assets");
74-
var appResourcesDirectoryPath = path.join(assetsDirectoryPath, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME);
75-
shell.cp("-r", path.join(this.$projectData.projectDir, constants.APP_FOLDER_NAME), assetsDirectoryPath);
83+
var appSourceDirectory = path.join(this.$projectData.projectDir, constants.APP_FOLDER_NAME);
84+
var assetsDirectory = path.join(platformData.projectRoot, "assets");
85+
var resDirectory = path.join(platformData.projectRoot, "res");
86+
87+
shell.cp("-r", appSourceDirectory, assetsDirectory);
7688

89+
var appResourcesDirectoryPath = path.join(assetsDirectory, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME);
7790
if (this.$fs.exists(appResourcesDirectoryPath).wait()) {
78-
shell.cp("-r", path.join(appResourcesDirectoryPath, normalizedPlatformName, "*"), path.join(this.$projectData.platformsDir, platform, "res"));
91+
shell.cp("-r", path.join(appResourcesDirectoryPath, platformData.normalizedPlatformName, "*"), resDirectory);
7992
this.$fs.deleteDirectory(appResourcesDirectoryPath).wait();
8093
}
8194

82-
var files = helpers.enumerateFilesInDirectorySync(path.join(assetsDirectoryPath, constants.APP_FOLDER_NAME));
83-
var platformsAsString = platforms.join("|");
95+
return path.join(assetsDirectory, constants.APP_FOLDER_NAME);
8496

85-
_.each(files, fileName => {
86-
var platformInfo = AndroidProjectService.parsePlatformSpecificFileName(path.basename(fileName), platformsAsString);
87-
var shouldExcludeFile = platformInfo && platformInfo.platform !== platform;
88-
if (shouldExcludeFile) {
89-
this.$fs.deleteFile(fileName).wait();
90-
} else if (platformInfo && platformInfo.onDeviceName) {
91-
this.$fs.rename(fileName, path.join(path.dirname(fileName), platformInfo.onDeviceName)).wait();
92-
}
93-
});
94-
}).future<void>()();
97+
}).future<string>()();
9598
}
9699

97100
public buildProject(projectRoot: string): IFuture<void> {
98101
return (() => {
99102
var buildConfiguration = options.release ? "release" : "debug";
100103
var args = this.getAntArgs(buildConfiguration, projectRoot);
101-
this.spawn('ant', args);
104+
this.spawn('ant', args).wait();
102105
}).future<void>()();
103106
}
104107

105-
private spawn(command: string, args: string[], options?: any): void {
106-
if(helpers.isWindows()) {
108+
private spawn(command: string, args: string[]): IFuture<void> {
109+
if (helpers.isWindows()) {
107110
args.unshift('/s', '/c', command);
108111
command = 'cmd';
109112
}
110113

111-
this.$childProcess.spawn(command, args, {cwd: options, stdio: 'inherit'});
114+
var child = this.$childProcess.spawn(command, args, {stdio: "inherit"});
115+
return this.$fs.futureFromEvent(child, "close");
112116
}
113117

114118
private getAntArgs(configuration: string, projectRoot: string): string[] {
@@ -123,7 +127,7 @@ class AndroidProjectService implements IPlatformProjectService {
123127
"--target", targetApi
124128
];
125129

126-
this.spawn("android update project", args);
130+
this.spawn("android", ['update', 'project'].concat(args)).wait();
127131
}).future<void>()();
128132
}
129133

@@ -208,17 +212,5 @@ class AndroidProjectService implements IPlatformProjectService {
208212
}
209213
}).future<void>()();
210214
}
211-
212-
private static parsePlatformSpecificFileName(fileName: string, platforms: string): any {
213-
var regex = util.format("^(.+?)\.(%s)(\..+?)$", platforms);
214-
var parsed = fileName.toLowerCase().match(new RegExp(regex, "i"));
215-
if (parsed) {
216-
return {
217-
platform: parsed[2],
218-
onDeviceName: parsed[1] + parsed[3]
219-
};
220-
}
221-
return undefined;
222-
}
223215
}
224216
$injector.register("androidProjectService", AndroidProjectService);

0 commit comments

Comments
 (0)