ask-cli
Version:
Alexa Skills Kit (ASK) Command Line Interfaces
212 lines (211 loc) • 6.87 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetricClient = exports.MetricAction = exports.MetricActionResult = void 0;
const uuid_1 = require("uuid");
const axios_1 = __importDefault(require("axios"));
const app_config_1 = __importDefault(require("../../model/app-config"));
const profile_helper_1 = __importDefault(require("../../utils/profile-helper"));
const constants_1 = require("../../utils/constants");
const package_json_1 = __importDefault(require("../../../package.json"));
exports.MetricActionResult = {
SUCCESS: "Success",
FAILURE: "Failure",
};
/**
* Metric action includes the name and results of CLI command.
*/
class MetricAction {
/**
* @constructor
* @param name - The action name.
* @param type - The action type.
*/
constructor(name, type) {
this.endTime = null;
this.failureMessage = "";
this.name = name;
this.result = null;
this.startTime = new Date();
this.type = type;
this.id = (0, uuid_1.v4)();
this.options = [];
this.optionData = {};
this._ended = false;
}
/**
* Add option to list, store value only if in {@link METRICS.STOREABLE_KEYS}
* @param optionName name of the option
* @param optionValue value of the option
*/
setOption(optionName, optionValue) {
const schemaOption = optionName.split("-").join("_");
this.options.push(schemaOption);
if (constants_1.METRICS.STOREABLE_KEYS.includes(schemaOption)) {
this.optionData[schemaOption] = optionValue;
}
}
/**
* Closes action
* @param error Error object or string indicating error.
*/
end(error = null) {
if (this._ended)
return;
// if Error object extract error message,
// otherwise error message string or null was passed as a parameter
const errorMessage = error && error instanceof Error ? error.message : error;
this.result = errorMessage ? exports.MetricActionResult.FAILURE : exports.MetricActionResult.SUCCESS;
this.failureMessage = errorMessage || "";
this.endTime = new Date();
this._ended = true;
}
/**
* Implementation of custom toJSON method to modify serialization with JSON.stringify
*/
toJSON() {
return {
end_time: this.endTime,
failure_message: this.failureMessage,
name: this.name,
result: this.result,
start_time: this.startTime,
type: this.type,
id: this.id,
options: this.options,
...this.optionData,
};
}
}
exports.MetricAction = MetricAction;
/**
* Client that communicates with telemetry endpoint.
*/
class MetricClient {
/**
* @constructor
*/
constructor() {
this.httpClient = axios_1.default.create({
timeout: 3000,
headers: { "Content-Type": "text/plain" },
});
this.serverUrl = constants_1.METRICS.ENDPOINT;
this.postRetries = 3;
this.enabled = this._isEnabled();
// initialize data
this.data = {
version: package_json_1.default.version,
machineId: this._getMachineId(),
timeStarted: new Date(),
newUser: false,
timeUploaded: null,
clientId: package_json_1.default.name,
actions: [],
};
}
/**
* Starts action
* @param name - The action name
* @param type - The action type
* @return the metric action that was started, {@link MetricAction}
*/
startAction(name, type) {
const action = new MetricAction(name, type);
this.data.actions.push(action);
return action;
}
/**
* Set option for the most recently started action
* @param optionName name of the option
* @param optionValue value of the option
*/
setOption(optionName, optionValue) {
const actions = this.data.actions;
if (actions.length) {
actions[actions.length - 1].setOption(optionName, optionValue);
}
}
/**
* Returns current data store in the metric client
* @return the metric data, {@link MetricClientData}
*/
getData() {
return this.data;
}
/**
* Sends data to the metric server
* @param error - Error object or string indicating error.
* @returns whether data was sent successfully
*/
async sendData(error = null) {
if (!this.enabled) {
this.data.actions = [];
return { success: true };
}
this.data.actions.forEach((action) => action.end(error));
try {
await this._upload();
this.data.actions = [];
return { success: true };
}
catch (_a) {
return { success: false };
}
}
/**
* Implementation of custom toJSON method to modify serialization with JSON.stringify
*/
toJSON() {
return {
version: this.data.version,
machine_id: this.data.machineId,
time_started: this.data.timeStarted,
new_user: this.data.newUser,
time_uploaded: this.data.timeUploaded,
client_id: this.data.clientId,
actions: this.data.actions,
};
}
async _upload() {
this.data.timeUploaded = new Date();
const payload = JSON.stringify({ payload: this });
const postPromise = () => this.httpClient.post(this.serverUrl, payload);
await this._retry(this.postRetries, postPromise);
}
async _retry(retries, func) {
try {
await func();
}
catch (error) {
if (retries == 1)
throw error;
await this._retry(retries - 1, func);
}
}
_isEnabled() {
if (profile_helper_1.default.isEnvProfile())
return true;
if (process.env.ASK_SHARE_USAGE === "false")
return false;
if (!app_config_1.default.configFileExists())
return false;
new app_config_1.default();
return app_config_1.default.getInstance().getShareUsage();
}
_getMachineId() {
if (!this.enabled)
return "";
if (profile_helper_1.default.isEnvProfile())
return "all_environmental";
const appConfig = app_config_1.default.getInstance();
if (!appConfig.getMachineId()) {
appConfig.setMachineId((0, uuid_1.v4)());
appConfig.write();
}
return appConfig.getMachineId();
}
}
exports.MetricClient = MetricClient;