Skip to content

Kddimitrov/track command options #4181

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 9 commits into from
Dec 4, 2018
1 change: 1 addition & 0 deletions lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ $injector.require("bundleValidatorHelper", "./helpers/bundle-validator-helper");
$injector.require("androidBundleValidatorHelper", "./helpers/android-bundle-validator-helper");
$injector.require("liveSyncCommandHelper", "./helpers/livesync-command-helper");
$injector.require("deployCommandHelper", "./helpers/deploy-command-helper");
$injector.require("optionsTracker", "./helpers/options-track-helper");

$injector.requirePublicClass("localBuildService", "./services/local-build-service");
$injector.requirePublicClass("liveSyncService", "./services/livesync/livesync-service");
Expand Down
4 changes: 4 additions & 0 deletions lib/common/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,10 @@ interface IDashedOption {
* Type of the option. It can be string, boolean, Array, etc.
*/
type: string;
/**
* Should skip in tracking
*/
private?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

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

private -> hasSensitiveValue

/**
* Shorthand option passed on the command line with `-` sign, for example `-v`
*/
Expand Down
4 changes: 3 additions & 1 deletion lib/common/services/commands-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export class CommandsService implements ICommandsService {
private $resources: IResourceLoader,
private $staticConfig: Config.IStaticConfig,
private $helpService: IHelpService,
private $extensibilityService: IExtensibilityService) {
private $extensibilityService: IExtensibilityService,
private $optionsTracker: IOptionsTracker) {
}

public allCommands(opts: { includeDevCommands: boolean }): string[] {
Expand Down Expand Up @@ -63,6 +64,7 @@ export class CommandsService implements ICommandsService {
}

await analyticsService.trackInGoogleAnalytics(googleAnalyticsPageData);
await this.$optionsTracker.trackOptions(this.$options);
}

const shouldExecuteHooks = !this.$staticConfig.disableCommandHooks && (command.enableHooks === undefined || command.enableHooks === true);
Expand Down
3 changes: 2 additions & 1 deletion lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ export const enum TrackActionNames {
LiveSync = "LiveSync",
RunSetupScript = "Run Setup Script",
CheckLocalBuildSetup = "Check Local Build Setup",
CheckEnvironmentRequirements = "Check Environment Requirements"
CheckEnvironmentRequirements = "Check Environment Requirements",
Options = "Options"
}

export const AnalyticsEventLabelDelimiter = "__";
Expand Down
4 changes: 4 additions & 0 deletions lib/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,10 @@ interface IAndroidBundleValidatorHelper {
validateRuntimeVersion(projectData: IProjectData): void
}

interface IOptionsTracker {
trackOptions(options: IOptions): Promise<void>
}

interface INativeScriptCloudExtensionService {
/**
* Installs nativescript-cloud extension
Expand Down
80 changes: 80 additions & 0 deletions lib/helpers/options-track-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import * as path from "path";
import { TrackActionNames } from "../constants";

export class OptionsTracker {
public static PASSWORD_DETECTION_STRING = "password";
public static PRIVATE_REPLACE_VALUE = "private";
public static PATH_REPLACE_VALUE = "_localpath";
public static SIZE_EXEEDED_REPLACE_VALUE = "sizeExceeded";

constructor(
private $analyticsService: IAnalyticsService) {
}

public async trackOptions(options: IOptions) {
const trackObject = this.getTrackObject(options);

await this.$analyticsService.trackEventActionInGoogleAnalytics({
action: TrackActionNames.Options,
additionalData: JSON.stringify(trackObject)
});
}

private getTrackObject(options: IOptions): IDictionary<any> {
const optionsArgvCopy = _.cloneDeep(options.argv);

return this.sanitizeTrackObject(optionsArgvCopy, options);
}

private sanitizeTrackObject(data: IDictionary<any>, options?: IOptions): IDictionary<any> {
const shorthands = options ? options.shorthands : [];
const optionsDefinitions = options ? options.options : {};

_.forEach(data, (value, key) => {
if (this.shouldSkipProperty(key, value, shorthands, optionsDefinitions)) {
delete data[key];
} else {
if (options && optionsDefinitions[key] && optionsDefinitions[key].private) {
value = OptionsTracker.PRIVATE_REPLACE_VALUE;
} else if (key.toLowerCase().indexOf(OptionsTracker.PASSWORD_DETECTION_STRING) >= 0) {
value = OptionsTracker.PRIVATE_REPLACE_VALUE;
} else if (_.isString(value) && value !== path.basename(value)) {
value = OptionsTracker.PATH_REPLACE_VALUE;
} else if (_.isObject(value) && !_.isArray(value)) {
value = this.sanitizeTrackObject(value);
}

data[key] = value;
}
});

return data;
}

private shouldSkipProperty(key: string, value: any, shorthands: string[] = [], options: IDictionary<IDashedOption> = {}): Boolean {
if (shorthands.indexOf(key) >= 0) {
return true;
}

if (key.indexOf("-") >= 0) {
return true;
}

if (key === "_") {
return true;
}

const optionDef = options[key];
if (optionDef && optionDef.type === OptionType.Boolean) {
if (optionDef.default !== true && value === false || optionDef.default === true && value === true) {
return true;
}
}

if (_.isUndefined(value)) {
return true;
}
}
}

$injector.register("optionsTracker", OptionsTracker);
36 changes: 19 additions & 17 deletions lib/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export class Options {
verbose: { type: OptionType.Boolean, alias: "v" },
version: { type: OptionType.Boolean },
help: { type: OptionType.Boolean, alias: "h" },
profileDir: { type: OptionType.String },
profileDir: { type: OptionType.String, private: true },
analyticsClient: { type: OptionType.String },
path: { type: OptionType.String, alias: "p" },
path: { type: OptionType.String, alias: "p", private: true },
// This will parse all non-hyphenated values as strings.
_: { type: OptionType.String }
};
Expand Down Expand Up @@ -47,14 +47,14 @@ export class Options {
framework: { type: OptionType.String },
frameworkVersion: { type: OptionType.String },
forDevice: { type: OptionType.Boolean },
provision: { type: OptionType.Object },
provision: { type: OptionType.Object, private: true },
client: { type: OptionType.Boolean, default: true },
env: { type: OptionType.Object },
production: { type: OptionType.Boolean },
debugTransport: { type: OptionType.Boolean },
keyStorePath: { type: OptionType.String },
keyStorePassword: { type: OptionType.String, },
keyStoreAlias: { type: OptionType.String },
keyStoreAlias: { type: OptionType.String, private: true },
keyStoreAliasPassword: { type: OptionType.String },
ignoreScripts: { type: OptionType.Boolean },
disableNpmInstall: { type: OptionType.Boolean },
Expand All @@ -75,46 +75,48 @@ export class Options {
androidTypings: { type: OptionType.Boolean },
bundle: { type: OptionType.String },
all: { type: OptionType.Boolean },
teamId: { type: OptionType.Object },
teamId: { type: OptionType.Object, private: true },
syncAllFiles: { type: OptionType.Boolean, default: false },
chrome: { type: OptionType.Boolean },
inspector: { type: OptionType.Boolean },
clean: { type: OptionType.Boolean },
watch: { type: OptionType.Boolean, default: true },
background: { type: OptionType.String },
username: { type: OptionType.String },
username: { type: OptionType.String, private: true },
pluginName: { type: OptionType.String },
hmr: { type: OptionType.Boolean },
collection: { type: OptionType.String, alias: "c" },
json: { type: OptionType.Boolean },
avd: { type: OptionType.String },
avd: { type: OptionType.String, private: true },
// check not used
config: { type: OptionType.Array },
insecure: { type: OptionType.Boolean, alias: "k" },
debug: { type: OptionType.Boolean, alias: "d" },
timeout: { type: OptionType.String },
device: { type: OptionType.String },
availableDevices: { type: OptionType.Boolean },
appid: { type: OptionType.String },
geny: { type: OptionType.String },
device: { type: OptionType.String, private: true },
availableDevices: { type: OptionType.Boolean, private: true },
appid: { type: OptionType.String, private: true },
geny: { type: OptionType.String, private: true },
debugBrk: { type: OptionType.Boolean },
debugPort: { type: OptionType.Number },
start: { type: OptionType.Boolean },
stop: { type: OptionType.Boolean },
ddi: { type: OptionType.String }, // the path to developer disk image
ddi: { type: OptionType.String, private: true }, // the path to developer disk image
justlaunch: { type: OptionType.Boolean },
file: { type: OptionType.String },
file: { type: OptionType.String, private: true },
force: { type: OptionType.Boolean, alias: "f" },
// remove legacy
companion: { type: OptionType.Boolean },
emulator: { type: OptionType.Boolean },
sdk: { type: OptionType.String },
template: { type: OptionType.String },
certificate: { type: OptionType.String },
template: { type: OptionType.String, private: true },
certificate: { type: OptionType.String, private: true },
certificatePassword: { type: OptionType.String },
release: { type: OptionType.Boolean, alias: "r" },
var: { type: OptionType.Object },
var: { type: OptionType.Object, private: true },
default: { type: OptionType.Boolean },
count: { type: OptionType.Number },
analyticsLogFile: { type: OptionType.String },
analyticsLogFile: { type: OptionType.String, private: true },
hooks: { type: OptionType.Boolean, default: true },
link: { type: OptionType.Boolean, default: false },
aab: { type: OptionType.Boolean }
Expand Down
3 changes: 3 additions & 0 deletions test/platform-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ function createTestInjector() {
testInjector.register("pacoteService", {
extractPackage: async (packageName: string, destinationDirectory: string, options?: IPacoteExtractOptions): Promise<void> => undefined
});
testInjector.register("optionsTracker", {
trackOptions: () => Promise.resolve(null)
});
testInjector.register("usbLiveSyncService", ({}));

return testInjector;
Expand Down
3 changes: 3 additions & 0 deletions test/plugins-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ function createTestInjector() {
testInjector.register("logger", stubs.LoggerStub);
testInjector.register("staticConfig", StaticConfig);
testInjector.register("hooksService", stubs.HooksServiceStub);
testInjector.register("optionsTracker", {
trackOptions: () => Promise.resolve(null)
});
testInjector.register("commandsService", CommandsService);
testInjector.register("commandsServiceProvider", {
registerDynamicSubCommands: () => { /* intentionally empty body */ }
Expand Down