Skip to content

Commit ed859b8

Browse files
committed
Init command
1 parent f95a53a commit ed859b8

File tree

9 files changed

+169
-4
lines changed

9 files changed

+169
-4
lines changed

docs/man_pages/project/creation/create.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,12 @@ Creates a new project for native development with NativeScript from the default
1616
* `<App Name>` is the name of project. The specified name must meet the requirements of all platforms that you want to target. <% if(isConsole) { %>For more information about the `<App Name>` requirements, run `$ tns help create`<% } %><% if(isHtml) { %>For projects that target Android, you can use uppercase or lowercase letters, numbers, and underscores. The name must start with a letter.
1717
For projects that target iOS, you can use uppercase or lowercase letters, numbers, and hyphens.<% } %>
1818
* `<App ID>` is the application identifier for your project. It must be a domain name in reverse and must meet the requirements of all platforms that you want to target. If not specified, the application identifier is set to `org.nativescript.<App name>` <% if(isConsole) { %>For more information about the `<App ID>` requirements, run `$ tns help create`<% } %><% if(isHtml) { %>For projects that target Android, you can use uppercase or lowercase letters, numbers, and underscores in the strings of the reversed domain name, separated by a dot. Strings must be separated by a dot and must start with a letter. For example: `com.nativescript.My_Andro1d_App`
19-
For projects that target iOS, you can use uppercase or lowercase letters, numbers, and hyphens in the strings of the reversed domain name. Strings must be separated by a dot. For example: `com.nativescript.My-i0s-App`.<% } %>
19+
For projects that target iOS, you can use uppercase or lowercase letters, numbers, and hyphens in the strings of the reversed domain name. Strings must be separated by a dot. For example: `com.nativescript.My-i0s-App`.<% } %>
20+
21+
<% if(isHtml) { %>
22+
### Related Commands
23+
24+
Command | Description
25+
----------|----------
26+
[init](init.html) | Initializes a project for development. It will ask you interactively to configure the project and will write a package.json for you.
27+
<% } %>
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
init
2+
==========
3+
4+
Usage | Synopsis
5+
---|---
6+
General | `$ tns init [--path <Directory>] [--force]`
7+
8+
Initializes a project for development. It will ask you interactively to configure the project and will write a package.json for you.
9+
10+
### Options
11+
* `--path` - Specifies the directory where you want to initialize the project, if different from the current directory. The directory must be empty.
12+
* `--force` - Will use only defaults and not prompt you for any options.
13+
14+
<% if(isHtml) { %>
15+
### Related Commands
16+
17+
Command | Description
18+
----------|----------
19+
[create](create.html) | Creates a new project for native development with NativeScript from the default template or from an existing NativeScript project.
20+
<% } %>

lib/bootstrap.ts

+1
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,6 @@ $injector.require("pluginsService", "./services/plugins-service");
6060
$injector.requireCommand("plugin|add", "./commands/plugin/add-plugin");
6161
$injector.requireCommand("plugin|remove", "./commands/plugin/remove-plugin");
6262
$injector.requireCommand("install", "./commands/install");
63+
$injector.requireCommand("init", "./commands/init");
6364

6465
$injector.require("projectFilesManager", "./services/project-files-manager");

lib/commands/init.ts

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
///<reference path="../.d.ts"/>
2+
"use strict";
3+
4+
import constants = require("./../constants");
5+
import helpers = require("./../common/helpers");
6+
import Future = require("fibers/future");
7+
import path = require("path");
8+
import semver = require("semver");
9+
10+
export class InitCommand implements ICommand {
11+
private static MIN_SUPPORTED_FRAMEWORK_VERSIONS: IStringDictionary = {
12+
"tns-ios": "1.1.0",
13+
"tns-android": "1.1.0"
14+
};
15+
16+
private _projectFilePath: string;
17+
18+
constructor(private $fs: IFileSystem,
19+
private $errors: IErrors,
20+
private $logger: ILogger,
21+
private $options: IOptions,
22+
private $injector: IInjector,
23+
private $staticConfig: IStaticConfig,
24+
private $projectHelper: IProjectHelper,
25+
private $prompter: IPrompter,
26+
private $npm: INodePackageManager,
27+
private $npmInstallationManager: INpmInstallationManager) { }
28+
29+
public allowedParameters: ICommandParameter[] = [];
30+
public enableHooks = false;
31+
32+
public execute(args: string[]): IFuture<void> {
33+
return (() => {
34+
let projectData: any = { };
35+
36+
if(this.$fs.exists(this.projectFilePath).wait()) {
37+
projectData = this.$fs.readJson(this.projectFilePath).wait();
38+
}
39+
40+
let projectDataBackup = _.extend({}, projectData);
41+
42+
if(!projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE]) {
43+
projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE] = { };
44+
this.$fs.writeJson(this.projectFilePath, projectData).wait(); // We need to create package.json file here in order to prevent "No project found at or above and neither was a --path specified." when resolving platformsData
45+
}
46+
47+
try {
48+
49+
projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE]["id"] = this.getProjectId().wait();
50+
51+
if(this.$options.frameworkName && this.$options.frameworkVersion) {
52+
projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE][this.$options.frameworkName] = this.buildVersionData(this.$options.frameworkVersion);
53+
} else {
54+
let $platformsData = this.$injector.resolve("platformsData");
55+
_.each($platformsData.platformsNames, platform => {
56+
let platformData: IPlatformData = $platformsData.getPlatformData(platform);
57+
if(!platformData.targetedOS || (platformData.targetedOS && _.contains(platformData.targetedOS, process.platform))) {
58+
projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE][platformData.frameworkPackageName] = this.getVersionData(platformData.frameworkPackageName).wait();
59+
}
60+
});
61+
}
62+
63+
this.$fs.writeJson(this.projectFilePath, projectData).wait();
64+
} catch(err) {
65+
this.$fs.writeJson(this.projectFilePath, projectDataBackup).wait();
66+
throw err;
67+
}
68+
69+
this.$logger.out("Project successfully initialized.");
70+
}).future<void>()();
71+
}
72+
73+
public canExecute(args: string[]): IFuture<boolean> {
74+
return Future.fromResult(true);
75+
}
76+
77+
private get projectFilePath(): string {
78+
if(!this._projectFilePath) {
79+
let projectPath = path.resolve(this.$options.path || ".");
80+
this._projectFilePath = path.join(projectPath, constants.PACKAGE_JSON_FILE_NAME);
81+
}
82+
83+
return this._projectFilePath;
84+
}
85+
86+
private set projectFilePath(newProjectFilePath: string) {
87+
this._projectFilePath = newProjectFilePath;
88+
}
89+
90+
private getProjectId(): IFuture<string> {
91+
return (() => {
92+
if(this.$options.appid) {
93+
return this.$options.appid;
94+
}
95+
96+
let defaultAppId = this.$projectHelper.generateDefaultAppId(path.basename(path.dirname(this.projectFilePath)), constants.DEFAULT_APP_IDENTIFIER_PREFIX);
97+
if(this.useDefaultValue) {
98+
return defaultAppId;
99+
}
100+
101+
return this.$prompter.getString("Id:", () => defaultAppId).wait();
102+
}).future<string>()();
103+
}
104+
105+
private getVersionData(packageName: string): IFuture<IStringDictionary> {
106+
return (() => {
107+
let latestVersion = this.$npmInstallationManager.getLatestVersion(packageName).wait();
108+
if(this.useDefaultValue) {
109+
return this.buildVersionData(latestVersion);
110+
}
111+
112+
let data = this.$npm.view(packageName, "versions").wait();
113+
let versions = _.filter(data[latestVersion].versions, (version: string) => semver.gte(version, InitCommand.MIN_SUPPORTED_FRAMEWORK_VERSIONS[packageName]));
114+
if(versions.length === 1) {
115+
this.$logger.info(`Only ${versions[0]} version is available for ${packageName} framework.`);
116+
return this.buildVersionData(versions[0]);
117+
}
118+
let sortedVersions = versions.sort(helpers.versionCompare).reverse();
119+
let version = this.$prompter.promptForChoice(`${packageName} version:`, sortedVersions).wait();
120+
return this.buildVersionData(version);
121+
}).future<IStringDictionary>()();
122+
}
123+
124+
private buildVersionData(version: string) {
125+
return { "version": version };
126+
}
127+
128+
private get useDefaultValue(): boolean {
129+
return !helpers.isInteractive() || this.$options.force;
130+
}
131+
}
132+
$injector.registerCommand("init", InitCommand);

lib/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export var NATIVESCRIPT_KEY_NAME = "nativescript";
77
export var NODE_MODULES_FOLDER_NAME = "node_modules";
88
export var PACKAGE_JSON_FILE_NAME = "package.json";
99
export var NODE_MODULE_CACHE_PATH_KEY_NAME = "node-modules-cache-path";
10+
export var DEFAULT_APP_IDENTIFIER_PREFIX = "org.nativescript";
1011

1112
export class ReleaseType {
1213
static MAJOR = "major";

lib/declarations.ts

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ interface IOpener {
5050

5151
interface IOptions extends ICommonOptions {
5252
frameworkPath: string;
53+
frameworkName: string;
54+
frameworkVersion: string;
5355
copyFrom: string;
5456
linkTo: string;
5557
release: boolean;

lib/options.ts

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export class Options extends commonOptionsLibPath.OptionsBase {
1313
$hostInfo: IHostInfo) {
1414
super({
1515
frameworkPath: { type: OptionType.String },
16+
frameworkName: { type: OptionType.String },
17+
frameworkVersion: { type: OptionType.String },
1618
copyFrom: { type: OptionType.String },
1719
linkTo: { type: OptionType.String },
1820
release: { type: OptionType.Boolean },

lib/services/project-service.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import shell = require("shelljs");
99
import util = require("util");
1010

1111
export class ProjectService implements IProjectService {
12-
private static DEFAULT_APP_IDENTIFIER_PREFIX = "org.nativescript";
1312

1413
constructor(private $errors: IErrors,
1514
private $fs: IFileSystem,
@@ -27,7 +26,7 @@ export class ProjectService implements IProjectService {
2726
}
2827
this.$projectNameValidator.validate(projectName);
2928

30-
var projectId = this.$options.appid || this.$projectHelper.generateDefaultAppId(projectName, ProjectService.DEFAULT_APP_IDENTIFIER_PREFIX);
29+
var projectId = this.$options.appid || this.$projectHelper.generateDefaultAppId(projectName, constants.DEFAULT_APP_IDENTIFIER_PREFIX);
3130

3231
var projectDir = path.join(path.resolve(this.$options.path || "."), projectName);
3332
this.$fs.createDirectory(projectDir).wait();

0 commit comments

Comments
 (0)