Skip to content

Commit b1e57b3

Browse files
Merge pull request NativeScript#4984 from NativeScript/vladimirov/analytics-company
feat: add tracking in analytics for company using NativeScript CLI
2 parents 602f450 + 54a579f commit b1e57b3

25 files changed

+1206
-142
lines changed

config/config.json

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"DISABLE_HOOKS": false,
77
"UPLOAD_PLAYGROUND_FILES_ENDPOINT": "https://play.nativescript.org/api/files",
88
"SHORTEN_URL_ENDPOINT": "https://play.nativescript.org/api/shortenurl?longUrl=%s",
9+
"INSIGHTS_URL_ENDPOINT": "https://play-server.nativescript.org/api/insights?ipAddress=%s",
10+
"WHOAMI_URL_ENDPOINT": "https://play.nativescript.org/api/whoami",
911
"PREVIEW_APP_ENVIRONMENT": "live",
1012
"GA_TRACKING_ID": "UA-111455-51"
1113
}

lib/bootstrap.ts

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ $injector.require("userSettingsService", "./services/user-settings-service");
6767
$injector.requirePublic("analyticsSettingsService", "./services/analytics-settings-service");
6868
$injector.require("analyticsService", "./services/analytics/analytics-service");
6969
$injector.require("googleAnalyticsProvider", "./services/analytics/google-analytics-provider");
70+
$injector.requirePublicClass("companyInsightsController", "./controllers/company-insights-controller");
7071

7172
$injector.require("platformCommandParameter", "./platform-command-param");
7273
$injector.requireCommand("create", "./commands/create-project");
@@ -228,3 +229,5 @@ $injector.require("watchIgnoreListService", "./services/watch-ignore-list-servic
228229
$injector.requirePublicClass("initializeService", "./services/initialize-service");
229230

230231
$injector.require("npmConfigService", "./services/npm-config-service");
232+
$injector.require("ipService", "./services/ip-service");
233+
$injector.require("jsonFileSettingsService", "./common/services/json-file-settings-service");

lib/common/declarations.d.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -1229,9 +1229,8 @@ interface IPlistParser {
12291229
parseFileSync(plistFilePath: string): any;
12301230
}
12311231

1232-
interface IUserSettingsService extends UserSettings.IUserSettingsService {
1233-
loadUserSettingsFile(): Promise<void>;
1234-
saveSettings(data: IDictionary<{}>): Promise<void>;
1232+
interface IUserSettingsService extends IJsonFileSettingsService {
1233+
// keep for backwards compatibility
12351234
}
12361235

12371236
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
interface ICacheTimeoutOpts {
2+
cacheTimeout: number;
3+
}
4+
5+
interface IUseCacheOpts {
6+
useCaching: boolean;
7+
}
8+
9+
interface IJsonFileSettingsService {
10+
getSettingValue<T>(settingName: string, cacheOpts?: ICacheTimeoutOpts): Promise<T>;
11+
saveSetting<T>(key: string, value: T, cacheOpts?: IUseCacheOpts): Promise<void>;
12+
removeSetting(key: string): Promise<void>;
13+
loadUserSettingsFile(): Promise<void>;
14+
saveSettings(data: IDictionary<{}>, cacheOpts?: IUseCacheOpts): Promise<void>;
15+
}

lib/common/definitions/user-settings.d.ts

-7
This file was deleted.

lib/common/services/analytics/google-analytics-custom-dimensions.d.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@ declare const enum GoogleAnalyticsCustomDimensions {
77
nodeVersion = "cd6",
88
playgroundId = "cd7",
99
usedTutorial = "cd8",
10-
isShared = "cd9"
10+
isShared = "cd9",
11+
companyName = "cd10",
12+
companyCountry = "cd11",
13+
companyRevenue = "cd12",
14+
companyIndustries = "cd13",
15+
companyEmployeeCount = "cd14",
1116
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import * as path from "path";
2+
import { parseJson } from "../helpers";
3+
4+
export class JsonFileSettingsService implements IJsonFileSettingsService {
5+
private jsonSettingsFilePath: string = null;
6+
protected jsonSettingsData: any = null;
7+
private get lockFilePath(): string {
8+
return `${this.jsonSettingsFilePath}.lock`;
9+
}
10+
11+
constructor(jsonFileSettingsPath: string,
12+
private $fs: IFileSystem,
13+
private $lockService: ILockService,
14+
private $logger: ILogger) {
15+
this.jsonSettingsFilePath = jsonFileSettingsPath;
16+
}
17+
18+
public async getSettingValue<T>(settingName: string, cacheOpts?: { cacheTimeout: number }): Promise<T> {
19+
const action = async (): Promise<T> => {
20+
await this.loadUserSettingsFile();
21+
22+
if (this.jsonSettingsData && _.has(this.jsonSettingsData, settingName)) {
23+
const data = this.jsonSettingsData[settingName];
24+
const dataToReturn = data.modifiedByCacheMechanism ? data.value : data;
25+
if (cacheOpts && cacheOpts.cacheTimeout) {
26+
if (!data.modifiedByCacheMechanism) {
27+
// If data has no cache, but we want to check the timeout, consider the data as outdated.
28+
// this should be a really rare case
29+
return null;
30+
}
31+
32+
const currentTime = Date.now();
33+
if ((currentTime - data.time) > cacheOpts.cacheTimeout) {
34+
return null;
35+
}
36+
}
37+
38+
return dataToReturn;
39+
}
40+
41+
return null;
42+
};
43+
44+
return this.$lockService.executeActionWithLock<T>(action, this.lockFilePath);
45+
}
46+
47+
public async saveSetting<T>(key: string, value: T, cacheOpts?: { useCaching: boolean }): Promise<void> {
48+
const settingObject: any = {};
49+
settingObject[key] = value;
50+
51+
return this.saveSettings(settingObject, cacheOpts);
52+
}
53+
54+
public async removeSetting(key: string): Promise<void> {
55+
const action = async (): Promise<void> => {
56+
await this.loadUserSettingsFile();
57+
58+
delete this.jsonSettingsData[key];
59+
await this.saveSettings();
60+
};
61+
62+
return this.$lockService.executeActionWithLock<void>(action, this.lockFilePath);
63+
}
64+
65+
public saveSettings(data?: any, cacheOpts?: { useCaching: boolean }): Promise<void> {
66+
const action = async (): Promise<void> => {
67+
await this.loadUserSettingsFile();
68+
this.jsonSettingsData = this.jsonSettingsData || {};
69+
70+
_(data)
71+
.keys()
72+
.each(propertyName => {
73+
this.jsonSettingsData[propertyName] = cacheOpts && cacheOpts.useCaching && !data[propertyName].modifiedByCacheMechanism ? {
74+
time: Date.now(),
75+
value: data[propertyName],
76+
modifiedByCacheMechanism: true
77+
} : data[propertyName];
78+
});
79+
80+
this.$fs.writeJson(this.jsonSettingsFilePath, this.jsonSettingsData);
81+
};
82+
83+
return this.$lockService.executeActionWithLock<void>(action, this.lockFilePath);
84+
}
85+
86+
public async loadUserSettingsFile(): Promise<void> {
87+
if (!this.jsonSettingsData) {
88+
await this.loadUserSettingsData();
89+
}
90+
}
91+
92+
private async loadUserSettingsData(): Promise<void> {
93+
if (!this.$fs.exists(this.jsonSettingsFilePath)) {
94+
const unexistingDirs = this.getUnexistingDirectories(this.jsonSettingsFilePath);
95+
96+
this.$fs.writeFile(this.jsonSettingsFilePath, null);
97+
98+
// when running under 'sudo' we create the <path to home dir>/.local/share/.nativescript-cli dir with root as owner
99+
// and other Applications cannot access this directory anymore. (bower/heroku/etc)
100+
if (process.env.SUDO_USER) {
101+
for (const dir of unexistingDirs) {
102+
await this.$fs.setCurrentUserAsOwner(dir, process.env.SUDO_USER);
103+
}
104+
}
105+
}
106+
107+
const data = this.$fs.readText(this.jsonSettingsFilePath);
108+
109+
try {
110+
this.jsonSettingsData = parseJson(data);
111+
} catch (err) {
112+
this.$logger.trace(`Error while trying to parseJson ${data} data from ${this.jsonSettingsFilePath} file. Err is: ${err}`);
113+
this.$fs.deleteFile(this.jsonSettingsFilePath);
114+
}
115+
}
116+
117+
private getUnexistingDirectories(filePath: string): Array<string> {
118+
const unexistingDirs: Array<string> = [];
119+
let currentDir = path.join(filePath, "..");
120+
while (true) {
121+
// this directory won't be created.
122+
if (this.$fs.exists(currentDir)) {
123+
break;
124+
}
125+
unexistingDirs.push(currentDir);
126+
currentDir = path.join(currentDir, "..");
127+
}
128+
return unexistingDirs;
129+
}
130+
}
131+
132+
$injector.register("jsonFileSettingsService", JsonFileSettingsService, false);

lib/common/services/user-settings-service.ts

-107
This file was deleted.

0 commit comments

Comments
 (0)