Skip to content

Init command #605

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 1, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion docs/man_pages/project/creation/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,13 @@ Creates a new project for native development with NativeScript from the default
* `<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.
For projects that target iOS, you can use uppercase or lowercase letters, numbers, and hyphens.<% } %>
* `<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`
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`.<% } %>
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`.<% } %>

<% if(isHtml) { %>
### Related Commands

Command | Description
----------|----------
[init](init.html) | Initializes a project for development. The command prompts you to provide your project configuration interactively and uses the information to create a new package.json file or update the existing one.
[install](install.html) | Installs all platforms and dependencies described in the `package.json` file in the current directory.
<% } %>
21 changes: 21 additions & 0 deletions docs/man_pages/project/creation/init.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
init
==========

Usage | Synopsis
---|---
General | `$ tns init [--path <Directory>] [--force]`

Initializes a project for development. The command prompts you to provide your project configuration interactively and uses the information to create a new `package.json` file or update the existing one.

### Options
* `--path` - Specifies the directory where you want to initialize the project, if different from the current directory. The directory must be empty.
* `--force` - If set, applies the default project configuration and does not show the interactive prompt. The default project configuration targets the latest official runtimes and sets `org.nativescript.<folder_name>` for application identifier.

<% if(isHtml) { %>
### Related Commands

Command | Description
----------|----------
[create](create.html) | Creates a new project for native development with NativeScript from the default template or from an existing NativeScript project.
[install](install.html) | Installs all platforms and dependencies described in the `package.json` file in the current directory.
<% } %>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the install command here, as it is actually related to the init workflow.

3 changes: 3 additions & 0 deletions lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@ $injector.requireCommand("plugin|add", "./commands/plugin/add-plugin");
$injector.requireCommand("plugin|remove", "./commands/plugin/remove-plugin");
$injector.requireCommand("install", "./commands/install");

$injector.require("initService", "./services/init-service");
$injector.requireCommand("init", "./commands/init");

$injector.require("projectFilesManager", "./services/project-files-manager");
16 changes: 16 additions & 0 deletions lib/commands/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
///<reference path="../.d.ts"/>
"use strict";

import Future = require("fibers/future");

export class InitCommand implements ICommand {
constructor(private $initService: IInitService) { }

public allowedParameters: ICommandParameter[] = [];
public enableHooks = false;

public execute(args: string[]): IFuture<void> {
return this.$initService.initialize();
}
}
$injector.registerCommand("init", InitCommand);
2 changes: 1 addition & 1 deletion lib/common
Submodule common updated 3 files
+2 −1 declarations.d.ts
+2 −1 options.ts
+5 −1 prompter.ts
1 change: 1 addition & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export var NATIVESCRIPT_KEY_NAME = "nativescript";
export var NODE_MODULES_FOLDER_NAME = "node_modules";
export var PACKAGE_JSON_FILE_NAME = "package.json";
export var NODE_MODULE_CACHE_PATH_KEY_NAME = "node-modules-cache-path";
export var DEFAULT_APP_IDENTIFIER_PREFIX = "org.nativescript";

export class ReleaseType {
static MAJOR = "major";
Expand Down
6 changes: 6 additions & 0 deletions lib/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ interface IOpener {

interface IOptions extends ICommonOptions {
frameworkPath: string;
frameworkName: string;
frameworkVersion: string;
copyFrom: string;
linkTo: string;
release: boolean;
Expand All @@ -67,4 +69,8 @@ interface IOptions extends ICommonOptions {

interface IProjectFilesManager {
processPlatformSpecificFiles(directoryPath: string, platform: string, excludedDirs?: string[]): IFuture<void>;
}

interface IInitService {
initialize(): IFuture<void>;
}
2 changes: 2 additions & 0 deletions lib/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export class Options extends commonOptionsLibPath.OptionsBase {
$hostInfo: IHostInfo) {
super({
frameworkPath: { type: OptionType.String },
frameworkName: { type: OptionType.String },
frameworkVersion: { type: OptionType.String },
copyFrom: { type: OptionType.String },
linkTo: { type: OptionType.String },
release: { type: OptionType.Boolean },
Expand Down
120 changes: 120 additions & 0 deletions lib/services/init-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
///<reference path="../.d.ts"/>
"use strict";

import constants = require("./../constants");
import helpers = require("./../common/helpers");
import path = require("path");
import semver = require("semver");

export class InitService implements IInitService {
private static MIN_SUPPORTED_FRAMEWORK_VERSIONS: IStringDictionary = {
"tns-ios": "1.1.0",
"tns-android": "1.1.0"
};

private _projectFilePath: string;

constructor(private $fs: IFileSystem,
private $errors: IErrors,
private $logger: ILogger,
private $options: IOptions,
private $injector: IInjector,
private $staticConfig: IStaticConfig,
private $projectHelper: IProjectHelper,
private $prompter: IPrompter,
private $npm: INodePackageManager,
private $npmInstallationManager: INpmInstallationManager) { }

public initialize(): IFuture<void> {
return (() => {
let projectData: any = { };

if(this.$fs.exists(this.projectFilePath).wait()) {
projectData = this.$fs.readJson(this.projectFilePath).wait();
}

let projectDataBackup = _.extend({}, projectData);

if(!projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE]) {
projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE] = { };
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
}

try {

projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE]["id"] = this.getProjectId().wait();

if(this.$options.frameworkName && this.$options.frameworkVersion) {
projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE][this.$options.frameworkName] = this.buildVersionData(this.$options.frameworkVersion);
} else {
let $platformsData = this.$injector.resolve("platformsData");
_.each($platformsData.platformsNames, platform => {
let platformData: IPlatformData = $platformsData.getPlatformData(platform);
if(!platformData.targetedOS || (platformData.targetedOS && _.contains(platformData.targetedOS, process.platform))) {
projectData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE][platformData.frameworkPackageName] = this.getVersionData(platformData.frameworkPackageName).wait();
}
});
}

this.$fs.writeJson(this.projectFilePath, projectData).wait();
} catch(err) {
this.$fs.writeJson(this.projectFilePath, projectDataBackup).wait();
throw err;
}

this.$logger.out("Project successfully initialized.");
}).future<void>()();
}

private get projectFilePath(): string {
if(!this._projectFilePath) {
let projectDir = path.resolve(this.$options.path || ".");
this._projectFilePath = path.join(projectDir, constants.PACKAGE_JSON_FILE_NAME);
}

return this._projectFilePath;
}

private getProjectId(): IFuture<string> {
return (() => {
if(this.$options.appid) {
return this.$options.appid;
}

let defaultAppId = this.$projectHelper.generateDefaultAppId(path.basename(path.dirname(this.projectFilePath)), constants.DEFAULT_APP_IDENTIFIER_PREFIX);
if(this.useDefaultValue) {
return defaultAppId;
}

return this.$prompter.getString("Id:", () => defaultAppId).wait();
}).future<string>()();
}

private getVersionData(packageName: string): IFuture<IStringDictionary> {
return (() => {
let latestVersion = this.$npmInstallationManager.getLatestVersion(packageName).wait();
if(this.useDefaultValue) {
return this.buildVersionData(latestVersion);
}

let data = this.$npm.view(packageName, "versions").wait();
let versions = _.filter(data[latestVersion].versions, (version: string) => semver.gte(version, InitService.MIN_SUPPORTED_FRAMEWORK_VERSIONS[packageName]));
if(versions.length === 1) {
this.$logger.info(`Only ${versions[0]} version is available for ${packageName} framework.`);
return this.buildVersionData(versions[0]);
}
let sortedVersions = versions.sort(helpers.versionCompare).reverse();
let version = this.$prompter.promptForChoice(`${packageName} version:`, sortedVersions).wait();
return this.buildVersionData(version);
}).future<IStringDictionary>()();
}

private buildVersionData(version: string): IStringDictionary {
return { "version": version };
}

private get useDefaultValue(): boolean {
return !helpers.isInteractive() || this.$options.force;
}
}
$injector.register("initService", InitService);
3 changes: 1 addition & 2 deletions lib/services/project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import shell = require("shelljs");
import util = require("util");

export class ProjectService implements IProjectService {
private static DEFAULT_APP_IDENTIFIER_PREFIX = "org.nativescript";

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

var projectId = this.$options.appid || this.$projectHelper.generateDefaultAppId(projectName, ProjectService.DEFAULT_APP_IDENTIFIER_PREFIX);
var projectId = this.$options.appid || this.$projectHelper.generateDefaultAppId(projectName, constants.DEFAULT_APP_IDENTIFIER_PREFIX);

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