ask-cli
Version:
Alexa Skills Kit (ASK) Command Line Interfaces
179 lines (178 loc) • 8.1 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeSmapiCommander = void 0;
const commander_1 = require("commander");
const ask_smapi_sdk_1 = require("ask-smapi-sdk");
const string_utils_1 = require("../../utils/string-utils");
const cli_customization_processor_1 = require("./cli-customization-processor");
const option_model_json_1 = __importDefault(require("../option-model.json"));
const option_validator_1 = require("../option-validator");
const smapi_command_handler_1 = __importDefault(require("./smapi-command-handler"));
const parameters_map_1 = require("./customizations/parameters-map");
const metrics_1 = __importDefault(require("../../utils/metrics"));
const aliases_json_1 = __importDefault(require("./customizations/aliases.json"));
const upload_catalog_1 = require("./appended-commands/upload-catalog");
const export_package_1 = require("./appended-commands/export-package");
const get_task_1 = require("./appended-commands/get-task");
const search_task_1 = require("./appended-commands/search-task");
const defaultOptions = [
{
flags: `-${option_model_json_1.default.profile.alias}, --profile <profile>`,
description: option_model_json_1.default.profile.description,
shortName: option_model_json_1.default.profile.alias,
longName: "profile",
},
{
flags: "--full-response",
description: option_model_json_1.default["full-response"].description,
shortName: "",
longName: "full-response",
},
{
flags: "--debug",
description: option_model_json_1.default.debug.description,
shortName: "",
longName: "debug",
},
];
const defaultValues = new Map();
defaultValues.set("stage", "development");
const requiredTemplate = { true: "[REQUIRED]", false: "[OPTIONAL]" };
const jsonTemplate = {
true: "[JSON]: Option value is JSON string, accepts JSON file by using either:" +
'\n- "$(cat {filePath})", use "type" command to replace "cat" command in Windows.' +
'\n- "file:{filePath}", file descriptor with either absolute or relative file path.\n',
false: "",
};
const _makeEnumTemplate = (param) => (param.enum ? `[ENUM]: ${param.enum.join()}.\n` : "");
const _makeArrayTemplate = (param) => (param.isArray ? "[MULTIPLE]: Values can be separated by comma.\n" : "");
const _makeAlias = (kebabName) => (aliases_json_1.default[kebabName] ? `-${aliases_json_1.default[kebabName]},` : "");
const _makeOption = (param) => {
const name = parameters_map_1.apiToCommanderMap.get(param.name) || param.name;
const defaultValue = defaultValues.get(name);
const shouldMakeOptional = param.required && defaultValue;
if (shouldMakeOptional) {
param.required = false;
}
const paramName = (0, string_utils_1.kebabCase)(name);
const alias = _makeAlias(paramName);
const json = param.json || "false";
const enumTemplate = _makeEnumTemplate(param);
const arrayTemplate = _makeArrayTemplate(param);
return {
flags: `${alias}--${paramName} <${paramName}>`,
description: (`${requiredTemplate[param.required]} ${(param.description || "").trim()} \n` +
`${arrayTemplate}` +
`${jsonTemplate[json]}` +
`${enumTemplate} `).trim(),
defaultValue: shouldMakeOptional ? defaultValue : undefined,
shortName: alias,
longName: paramName,
};
};
/**
* Simple validation for options for which rules have been defined
* @param options option-value pairs that were specified
* @param id option id to lookup and validate
* @throws error if no rules found or input was invalid
*/
const _validateOption = (options, id) => {
const model = option_model_json_1.default;
const entry = model[id];
if (!entry)
throw `No entry with validation rules for ${id}.`;
const optionName = (0, string_utils_1.camelCase)(id);
try {
const value = options[optionName];
if (value) {
if (entry.stringInput === "REQUIRED")
(0, option_validator_1.validateOptionString)(options, optionName);
// validate remaining rules
(0, option_validator_1.validateOptionRules)(options, optionName, entry.rule);
}
}
catch (error) {
throw `Please provide valid input for option: ${entry.name}. ${error}`;
}
};
/**
* Initialize metrics for smapi operations
* @param command the command instance
* @param optionsList the list of options
*/
const _initializeMetrics = (command, optionsList) => {
metrics_1.default.startAction("smapi", command.name());
const optionsProvided = command.opts();
optionsList.forEach((option) => {
const name = option.longName, value = optionsProvided[(0, string_utils_1.camelCase)(name)];
if (value === undefined)
return; // option was not set
// metric client requires input validation when storing values
try {
_validateOption(optionsProvided, name);
metrics_1.default.setOption(name, value);
}
catch (error) {
metrics_1.default.setOption(name, "");
}
});
};
/**
* Creates commander instance for Smapi operations.
*/
const makeSmapiCommander = () => {
const customizationProcessor = new cli_customization_processor_1.CliCustomizationProcessor();
const modelIntrospector = new ask_smapi_sdk_1.ModelIntrospector(null, customizationProcessor);
const operations = modelIntrospector.getOperations();
const program = new commander_1.Command();
let commanderInstance;
operations.forEach((operation, commandName) => {
const commanderToApiCustomizationMap = new Map();
const { apiOperationName, description } = operation;
commanderInstance = program.command(commandName).description(description).storeOptionsAsProperties(false);
const { flatParamsMap } = operation.customizationMetadata;
const optionsList = [];
flatParamsMap.forEach((param) => {
const customizationValue = parameters_map_1.apiToCommanderMap.get(param.name);
if (customizationValue) {
commanderToApiCustomizationMap.set(customizationValue, param.name);
}
const option = _makeOption(param);
optionsList.push(option);
if (param.required) {
commanderInstance.requiredOption(option.flags, option.description);
}
else {
commanderInstance.option(option.flags, option.description, option.defaultValue);
}
});
defaultOptions.forEach((option) => {
commanderInstance.option(option.flags, option.description);
optionsList.push(option);
});
commanderInstance.action((inputCmdObj) => {
_initializeMetrics(inputCmdObj, optionsList);
return smapi_command_handler_1.default
.smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, inputCmdObj, modelIntrospector)
.then((res) => metrics_1.default.sendData().then(() => res))
.catch((err) => metrics_1.default.sendData(err).then(() => Promise.reject(err)));
});
});
// register hand-written appended commands
(0, upload_catalog_1.createCommand)(program);
(0, export_package_1.createCommand)(program);
(0, get_task_1.createCommand)(program);
(0, search_task_1.createCommand)(program);
program.name("ask smapi");
program.description("The smapi command provides a number of sub-commands that " +
"enable you to manage Alexa skills associated with your developer account.");
program.on("command:*", () => {
console.error(`Command not recognized. Please run "ask smapi" to check the user instructions.`);
process.exit(1);
});
return program;
};
exports.makeSmapiCommander = makeSmapiCommander;