-
-
Notifications
You must be signed in to change notification settings - Fork 197
/
Copy pathproject-templates-service.ts
113 lines (94 loc) · 5.18 KB
/
project-templates-service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import * as path from "path";
import * as temp from "temp";
import * as constants from "../constants";
import { format } from "util";
temp.track();
export class ProjectTemplatesService implements IProjectTemplatesService {
private templatePackageContents: IDictionary<any> = {};
public constructor(private $analyticsService: IAnalyticsService,
private $fs: IFileSystem,
private $logger: ILogger,
private $npmInstallationManager: INpmInstallationManager,
private $pacoteService: IPacoteService,
private $errors: IErrors) { }
public async prepareTemplate(originalTemplateName: string, projectDir: string): Promise<ITemplateData> {
if (!originalTemplateName) {
originalTemplateName = constants.RESERVED_TEMPLATE_NAMES["default"];
}
// support <reserved_name>@<version> syntax, for example [email protected]
// support <scoped_package_name>@<version> syntax, for example @nativescript/[email protected]
const lastIndexOfAtSign = originalTemplateName.lastIndexOf("@");
let name = originalTemplateName;
let version = "";
if (lastIndexOfAtSign > 0) {
name = originalTemplateName.substr(0, lastIndexOfAtSign);
version = originalTemplateName.substr(lastIndexOfAtSign + 1);
}
const templateName = constants.RESERVED_TEMPLATE_NAMES[name.toLowerCase()] || name;
const fullTemplateName = version ? `${templateName}@${version}` : templateName;
const templatePackageJsonContent = await this.getTemplatePackageJsonContent(fullTemplateName);
const templateVersion = await this.getTemplateVersion(fullTemplateName);
let templatePath = null;
if (templateVersion === constants.TemplateVersions.v1) {
templatePath = await this.prepareNativeScriptTemplate(templateName, version, projectDir);
// this removes dependencies from templates so they are not copied to app folder
this.$fs.deleteDirectory(path.join(templatePath, constants.NODE_MODULES_FOLDER_NAME));
}
await this.$analyticsService.track("Template used for project creation", templateName);
const templateNameToBeTracked = this.getTemplateNameToBeTracked(templateName, templatePackageJsonContent);
if (templateNameToBeTracked) {
await this.$analyticsService.trackEventActionInGoogleAnalytics({
action: constants.TrackActionNames.CreateProject,
isForDevice: null,
additionalData: templateNameToBeTracked
});
await this.$analyticsService.trackEventActionInGoogleAnalytics({
action: constants.TrackActionNames.UsingTemplate,
additionalData: `${templateNameToBeTracked}${constants.AnalyticsEventLabelDelimiter}${templateVersion}`
});
}
return { templateName, templatePath, templateVersion, templatePackageJsonContent, version };
}
private async getTemplateVersion(templateName: string): Promise<string> {
const packageJsonContent = await this.getTemplatePackageJsonContent(templateName);
const templateVersionFromPackageJson: string = packageJsonContent && packageJsonContent.nativescript && packageJsonContent.nativescript.templateVersion;
if (templateVersionFromPackageJson) {
this.$logger.trace(`The template ${templateName} has version ${templateVersionFromPackageJson}.`);
if (_.values(constants.TemplateVersions).indexOf(templateVersionFromPackageJson) === -1) {
this.$errors.failWithoutHelp(format(constants.ProjectTemplateErrors.InvalidTemplateVersionStringFormat, templateName, templateVersionFromPackageJson));
}
return templateVersionFromPackageJson;
}
return constants.TemplateVersions.v1;
}
private async getTemplatePackageJsonContent(templateName: string): Promise<ITemplatePackageJsonContent> {
if (!this.templatePackageContents[templateName]) {
this.templatePackageContents[templateName] = await this.$pacoteService.manifest(templateName, { fullMetadata: true });
}
return this.templatePackageContents[templateName];
}
/**
* Install verified NativeScript template in the npm cache.
* The "special" here is that npmInstallationManager will check current CLI version and will instal best matching version of the template.
* For example in case CLI is version 10.12.8, npmInstallationManager will try to find latest 10.12.x version of the template.
* @param {string} templateName The name of the verified NativeScript template.
* @param {string} version The version of the template specified by user.
* @return {string} Path to the directory where the template is installed.
*/
private async prepareNativeScriptTemplate(templateName: string, version?: string, projectDir?: string): Promise<string> {
this.$logger.trace(`Using NativeScript verified template: ${templateName} with version ${version}.`);
return this.$npmInstallationManager.install(templateName, projectDir, { version: version, dependencyType: "save" });
}
private getTemplateNameToBeTracked(templateName: string, packageJsonContent: any): string {
try {
if (this.$fs.exists(templateName)) {
const templateNameToBeTracked = (packageJsonContent && packageJsonContent.name) || path.basename(templateName);
return `${constants.ANALYTICS_LOCAL_TEMPLATE_PREFIX}${templateNameToBeTracked}`;
}
return templateName;
} catch (err) {
this.$logger.trace(`Unable to get template name to be tracked, error is: ${err}`);
}
}
}
$injector.register("projectTemplatesService", ProjectTemplatesService);