Skip to content

Commit 111a986

Browse files
Merge pull request #1638 from NativeScript/milanov/add-angular-and-ng-template-parameters
Simplified creating angular template project
2 parents 219a1ad + 28202a7 commit 111a986

10 files changed

+172
-25
lines changed

docs/man_pages/project/creation/create.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ create
44
Usage | Synopsis
55
---|---
66
Create from default JavaScript template | `$ tns create <App Name> [--path <Directory>] [--appid <App ID>]`
7-
Create from default TypeScript template | `$ tns create <App Name> [--path <Directory>] [--appid <App ID> --template typescript` OR `$ tns create <App Name> [--path <Directory>] [--appid <App ID> --template tsc`
7+
Create from default TypeScript template | `$ tns create <App Name> --template typescript [--path <Directory>] [--appid <App ID>]` OR `$ tns create <App Name> --template tsc [--path <Directory>] [--appid <App ID>]`
8+
Create from default Angular template | `$ tns create <App Name> --template angular [--path <Directory>] [--appid <App ID>]` OR `$ tns create <App Name> --template ng [--path <Directory>] [--appid <App ID>]` OR `$ tns create <App Name> --ng [--path <Directory>] [--appid <App ID>]`
89
Copy from existing project | `$ tns create <App Name> [--path <Directory>] [--appid <App ID>] --copy-from <Directory>`
910
Create from custom template | `$ tns create <App Name> [--path <Directory>] [--appid <App ID>] --template <Template>`
1011

@@ -15,6 +16,7 @@ Creates a new project for native development with NativeScript.
1516
* `--appid` - Sets the application identifier for your project.
1617
* `--copy-from` - Specifies a directory which contains an existing NativeScript project. If `--copy-from` and `--template` are not set, the NativeScript CLI creates the project from the default JavaScript hello-world template.
1718
* `--template` - Specifies a valid npm package which you want to use to create your project. If `--copy-from` and `--template` are not set, the NativeScript CLI creates the project from the default JavaScript hello-world template.<% if(isHtml) { %> If one or more application assets are missing from the `App_Resources` directory in the package, the CLI adds them using the assets available in the default hello-world template.<% } %>
19+
* `--ng` - Sets the template for your project to the Angular template.
1820

1921
### Attributes
2022
* `<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.

lib/commands/create-project.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
///<reference path="../.d.ts"/>
22
"use strict";
33

4+
import * as constants from "../constants";
5+
46
export class ProjectCommandParameter implements ICommandParameter {
57
constructor(private $errors: IErrors,
68
private $logger: ILogger,
@@ -27,13 +29,19 @@ export class CreateProjectCommand implements ICommand {
2729
private $errors: IErrors,
2830
private $logger: ILogger,
2931
private $projectNameValidator: IProjectNameValidator,
30-
private $options: ICommonOptions) { }
32+
private $options: IOptions) { }
3133

3234
public enableHooks = false;
3335

3436
execute(args: string[]): IFuture<void> {
3537
return (() => {
36-
this.$projectService.createProject(args[0], this.$options.template).wait();
38+
if (this.$options.ng && this.$options.template) {
39+
this.$errors.fail("You cannot use --ng and --template simultaneously.");
40+
}
41+
42+
let selectedTemplate = this.$options.ng ? constants.ANGULAR_NAME : this.$options.template;
43+
44+
this.$projectService.createProject(args[0], selectedTemplate).wait();
3745
}).future<void>()();
3846
}
3947

lib/constants.ts

+2
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,5 @@ class ItunesConnectApplicationTypesClass implements IiTunesConnectApplicationTyp
4343
}
4444

4545
export let ItunesConnectApplicationTypes = new ItunesConnectApplicationTypesClass();
46+
47+
export let ANGULAR_NAME = "angular";

lib/declarations.ts

+20-19
Original file line numberDiff line numberDiff line change
@@ -58,32 +58,33 @@ interface ILiveSyncService {
5858
}
5959

6060
interface IOptions extends ICommonOptions {
61-
ipa: string;
62-
frameworkPath: string;
63-
frameworkName: string;
64-
framework: string;
65-
frameworkVersion: string;
61+
baseConfig: string;
62+
client: boolean;
63+
compileSdk: number;
6664
copyFrom: string;
67-
linkTo: string;
65+
copyTo: string;
66+
debugTransport: boolean;
6867
emulator: boolean;
69-
symlink: boolean;
7068
forDevice: boolean;
71-
client: boolean;
72-
production: boolean;
73-
keyStorePath: string;
74-
keyStorePassword: string;
69+
framework: string;
70+
frameworkName: string;
71+
frameworkPath: string;
72+
frameworkVersion: string;
73+
ignoreScripts: boolean;
74+
ipa: string;
7575
keyStoreAlias: string;
7676
keyStoreAliasPassword: string;
77+
keyStorePassword: string;
78+
keyStorePath: string;
79+
linkTo: string;
80+
ng: boolean;
81+
platformTemplate: string;
82+
port: Number;
83+
production: boolean;
7784
sdk: string;
78-
debugTransport: boolean;
79-
ignoreScripts: boolean;
80-
tnsModulesVersion: string;
8185
staticBindings: boolean;
82-
compileSdk: number;
83-
port: Number;
84-
copyTo: string;
85-
baseConfig: string;
86-
platformTemplate: string;
86+
symlink: boolean;
87+
tnsModulesVersion: string;
8788
}
8889

8990
interface IInitService {

lib/npm-installation-manager.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export class NpmInstallationManager implements INpmInstallationManager {
2020
"tns-ios": constants.PROJECT_FRAMEWORK_FOLDER_NAME,
2121
"tns-ios-inspector": "WebInspectorUI",
2222
"tns-template-hello-world": constants.APP_RESOURCES_FOLDER_NAME,
23-
"tns-template-hello-world-ts": constants.APP_RESOURCES_FOLDER_NAME
23+
"tns-template-hello-world-ts": constants.APP_RESOURCES_FOLDER_NAME,
24+
"tns-template-hello-world-ng": constants.APP_RESOURCES_FOLDER_NAME
2425
};
2526

2627
constructor(private $npm: INodePackageManager,

lib/options.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ export class Options extends commonOptionsLibPath.OptionsBase {
3535
port: { type: OptionType.Number },
3636
copyTo: { type: OptionType.String },
3737
baseConfig: { type: OptionType.String },
38-
platformTemplate: { type: OptionType.String }
38+
platformTemplate: { type: OptionType.String },
39+
ng: {type: OptionType.Boolean }
3940
},
4041
path.join($hostInfo.isWindows ? process.env.AppData : path.join(osenv.home(), ".local/share"), ".nativescript-cli"),
4142
$errors, $staticConfig);

lib/services/project-service.ts

+2
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ export class ProjectService implements IProjectService {
146146
this.$fs.symlink(appSourcePath, appDestinationPath).wait();
147147
} else {
148148
shelljs.cp('-R', path.join(appSourcePath, "*"), appDestinationPath);
149+
// Copy hidden files.
150+
shelljs.cp('-R', path.join(appSourcePath, ".*"), appDestinationPath);
149151
}
150152

151153
this.createBasicProjectStructure(projectDir, projectId).wait();

lib/services/project-templates-service.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ export class ProjectTemplatesService implements IProjectTemplatesService {
1010
private static RESERVED_TEMPLATE_NAMES: IStringDictionary = {
1111
"default": "tns-template-hello-world",
1212
"tsc": "tns-template-hello-world-ts",
13-
"typescript": "tns-template-hello-world-ts"
13+
"typescript": "tns-template-hello-world-ts",
14+
"ng": "tns-template-hello-world-ng",
15+
"angular": "tns-template-hello-world-ng"
1416
};
1517

1618
public constructor(private $errors: IErrors,

test/project-commands.ts

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/// <reference path=".d.ts" />
2+
"use strict";
3+
4+
import { Yok } from "../lib/common/yok";
5+
import * as stubs from "./stubs";
6+
import { CreateProjectCommand } from "../lib/commands/create-project";
7+
import * as constants from "../lib/constants";
8+
import {assert} from "chai";
9+
10+
let selectedTemplateName: string;
11+
let isProjectCreated: boolean;
12+
let dummyArgs = ["dummyArgsString"];
13+
14+
class ProjectServiceMock implements IProjectService {
15+
createProject(projectName: string, selectedTemplate?: string): IFuture<void> {
16+
return (() => {
17+
selectedTemplateName = selectedTemplate;
18+
isProjectCreated = true;
19+
}).future<void>()();
20+
}
21+
}
22+
23+
class ProjectNameValidatorMock implements IProjectNameValidator {
24+
public validate(name: string): boolean {
25+
return true;
26+
}
27+
}
28+
29+
function createTestInjector() {
30+
let testInjector = new Yok();
31+
32+
testInjector.register("injector", testInjector);
33+
testInjector.register("staticConfig", {});
34+
testInjector.register("projectService", ProjectServiceMock);
35+
testInjector.register("errors", stubs.ErrorsStub);
36+
testInjector.register("logger", stubs.LoggerStub);
37+
testInjector.register("projectNameValidator", ProjectNameValidatorMock);
38+
testInjector.register("options", {
39+
ng: false,
40+
template: undefined
41+
});
42+
testInjector.register("createCommand", CreateProjectCommand);
43+
44+
return testInjector;
45+
}
46+
47+
describe("Project commands tests", () => {
48+
let testInjector: IInjector;
49+
let options: IOptions;
50+
let createProjectCommand: ICommand;
51+
52+
beforeEach(() => {
53+
testInjector = createTestInjector();
54+
isProjectCreated = false;
55+
selectedTemplateName = undefined;
56+
options = testInjector.resolve("$options");
57+
createProjectCommand = testInjector.resolve("$createCommand");
58+
});
59+
60+
describe("#CreateProjectCommand", () => {
61+
it("should not fail when using only --ng.", () => {
62+
options.ng = true;
63+
64+
createProjectCommand.execute(dummyArgs).wait();
65+
66+
assert.isTrue(isProjectCreated);
67+
});
68+
69+
it("should not fail when using only --template.", () => {
70+
options.template = "ng";
71+
72+
createProjectCommand.execute(dummyArgs).wait();
73+
74+
assert.isTrue(isProjectCreated);
75+
});
76+
77+
it("should set the template name correctly when used --ng.", () => {
78+
options.ng = true;
79+
80+
createProjectCommand.execute(dummyArgs).wait();
81+
82+
assert.deepEqual(selectedTemplateName, constants.ANGULAR_NAME);
83+
});
84+
85+
it("should not set the template name when --ng is not used.", () => {
86+
options.ng = false;
87+
88+
createProjectCommand.execute(dummyArgs).wait();
89+
90+
assert.isUndefined(selectedTemplateName);
91+
});
92+
93+
it("should fail when --ng and --template are used simultaneously.", () => {
94+
options.ng = true;
95+
options.template = "ng";
96+
97+
assert.throws(() => {
98+
createProjectCommand.execute(dummyArgs).wait();
99+
});
100+
});
101+
});
102+
});

test/project-service.ts

+26
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,32 @@ describe("Project Service Tests", () => {
210210
projectIntegrationTest.assertProject(tempFolder, projectName, "org.nativescript.myapp", projectTemplatesService.prepareTemplate("tsc").wait()).wait();
211211
});
212212

213+
it("creates valid project from angular template", () => {
214+
let projectIntegrationTest = new ProjectIntegrationTest();
215+
let tempFolder = temp.mkdirSync("projectAngular");
216+
let projectName = "myapp";
217+
let options = projectIntegrationTest.testInjector.resolve("options");
218+
219+
options.path = tempFolder;
220+
projectIntegrationTest.createProject(projectName, "angular").wait();
221+
222+
let projectTemplatesService: IProjectTemplatesService = projectIntegrationTest.testInjector.resolve("projectTemplatesService");
223+
projectIntegrationTest.assertProject(tempFolder, projectName, "org.nativescript.myapp", projectTemplatesService.prepareTemplate("angular").wait()).wait();
224+
});
225+
226+
it("creates valid project from ng template", () => {
227+
let projectIntegrationTest = new ProjectIntegrationTest();
228+
let tempFolder = temp.mkdirSync("projectNg");
229+
let projectName = "myapp";
230+
let options = projectIntegrationTest.testInjector.resolve("options");
231+
232+
options.path = tempFolder;
233+
projectIntegrationTest.createProject(projectName, "ng").wait();
234+
235+
let projectTemplatesService: IProjectTemplatesService = projectIntegrationTest.testInjector.resolve("projectTemplatesService");
236+
projectIntegrationTest.assertProject(tempFolder, projectName, "org.nativescript.myapp", projectTemplatesService.prepareTemplate("ng").wait()).wait();
237+
});
238+
213239
it("creates valid project from local directory template", () => {
214240
let projectIntegrationTest = new ProjectIntegrationTest();
215241
let tempFolder = temp.mkdirSync("projectLocalDir");

0 commit comments

Comments
 (0)