ask-cli-x
Version:
Alexa Skills Kit (ASK) Command Line Interfaces
208 lines (207 loc) • 9.61 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCommand = exports.DialogCommand = void 0;
const path = __importStar(require("path"));
const smapi_client_1 = require("../../clients/smapi-client");
const abstract_command_1 = require("../../commands/abstract-command");
const optionModel = __importStar(require("../../commands/option-model.json"));
const cli_error_1 = __importDefault(require("../../exceptions/cli-error"));
const dialog_replay_file_1 = __importDefault(require("../../model/dialog-replay-file"));
const resources_config_1 = __importDefault(require("../../model/resources-config"));
const jsonView = __importStar(require("../../view/json-view"));
const CONSTANTS = __importStar(require("../../utils/constants"));
const profileHelper = __importStar(require("../../utils/profile-helper"));
const messenger_1 = __importDefault(require("../../view/messenger"));
const spinner_view_1 = __importDefault(require("../../view/spinner-view"));
const stringUtils = __importStar(require("../../utils/string-utils"));
const interactive_mode_1 = require("./interactive-mode");
const replay_mode_1 = require("./replay-mode");
const helper_1 = require("./helper");
const evaluate_mode_1 = require("./evaluate-mode");
const evaluate_view_1 = require("../../view/evaluate-view");
class DialogCommand extends abstract_command_1.AbstractCommand {
constructor(smapiClient, optionModel) {
super(optionModel);
this.smapiClient = smapiClient;
this.messenger = messenger_1.default.getInstance();
}
name() {
return "dialog";
}
description() {
return "simulate your skill via an interactive dialog with Alexa";
}
requiredOptions() {
return [];
}
optionalOptions() {
return ["skill-id", "evaluate", "locale", "stage", "replay", "save-skill-io", "verbose", "profile", "debug"];
}
async handle(cmd) {
try {
const dialogMode = await this._dialogModeFactory(cmd);
const spinner = new spinner_view_1.default();
spinner.start("Checking if skill is ready to simulate...");
try {
await (0, helper_1.validateDialogArgs)(dialogMode);
}
catch (err) {
spinner.terminate(spinner_view_1.default.TERMINATE_STYLE.FAIL, "Failed to validate command options");
throw err;
}
spinner.terminate();
await dialogMode.start();
}
catch (err) {
this.messenger.error(err);
throw err;
}
}
/**
* Function processes dialog arguments and returns a consolidated object.
* @param {Object} cmd encapsulates arguments provided to the dialog command.
* @return { skillId, locale, stage, profile, debug, replayFile, smapiClient, userInputs <for replay mode> }
*/
async _getDialogConfig(cmd) {
var _a, _b;
const { skillId: cmdSkillId, locale: cmdLocale, stage: cmdStage, profile: cmdProfile } = cmd;
const { evaluate, saveSkillIo, verbose, debug } = cmd;
const profile = profileHelper.runtimeProfile(cmdProfile);
const stage = cmdStage || CONSTANTS.SKILL.STAGE.DEVELOPMENT;
const smapiClient = this.smapiClient.withConfiguration({
profile,
doDebug: !!cmd.debug,
});
const { skillId = cmdSkillId, locale = cmdLocale, userInputs } = this._resolvedArguments(cmd, profile);
const manifestResult = await smapiClient.skill.manifest.getManifest(skillId, stage);
if ((0, smapi_client_1.isSmapiError)(manifestResult)) {
throw jsonView.toString(manifestResult.body);
}
const [firstLocaleFromManifest] = Object.keys(((_b = (_a = manifestResult.body.manifest) === null || _a === void 0 ? void 0 : _a.publishingInformation) === null || _b === void 0 ? void 0 : _b.locales) || {});
if (!locale && !process.env.ASK_DEFAULT_DEVICE_LOCALE && firstLocaleFromManifest) {
this.messenger.info(`Defaulting locale to the first value from the skill manifest: ${firstLocaleFromManifest}`);
}
return {
skillId,
locale: locale || process.env.ASK_DEFAULT_DEVICE_LOCALE || firstLocaleFromManifest,
stage,
profile,
debug,
replay: cmd.replay,
evaluate,
verbose,
saveSkillIo,
smapiClient,
userInputs,
};
}
_resolvedArguments(cmd, profile) {
const { evaluate, verbose, skillId: cmdSkillId, locale } = cmd;
if (verbose && !evaluate) {
throw new cli_error_1.default("--verbose cannot be used without --evaluate");
}
if (cmd.replay) {
// try {
if (evaluate) {
throw new cli_error_1.default("Must not use both --replay and --evaluate, which are two modes working separately");
}
if (verbose) {
throw new cli_error_1.default("Must not use both --replay and --verbose as explanation must be turn based");
}
const dialogReplayConfig = new dialog_replay_file_1.default(cmd.replay);
const skillId = dialogReplayConfig.getSkillId();
if (!stringUtils.isNonBlankString(skillId)) {
throw new cli_error_1.default("Replay file must contain skillId");
}
const locale = dialogReplayConfig.getLocale();
if (!stringUtils.isNonBlankString(locale)) {
throw new cli_error_1.default("Replay file must contain locale");
}
return { userInputs: this._validateUserInputs(dialogReplayConfig.getUserInput()), skillId, locale };
}
else if (evaluate) {
if (locale) {
throw new cli_error_1.default("--locale cannot be used with --evaluate, as only en-US locale is supported now");
}
if (process.env.ASK_DEFAULT_DEVICE_LOCALE) {
throw new cli_error_1.default('Please unset environmental variable "ASK_DEFAULT_DEVICE_LOCALE" as locale is not supported in evaluate mode');
}
if (cmdSkillId) {
throw new cli_error_1.default("Please run --evaluate from a deployed skill project, where CLI can load the project and skillId");
}
const skillId = this._getSkillIdFromProfile(profile);
return { skillId };
}
else if (!stringUtils.isNonBlankString(cmdSkillId)) {
const skillId = this._getSkillIdFromProfile(profile);
return { skillId };
}
return {};
}
_getSkillIdFromProfile(profile) {
let skillId;
try {
new resources_config_1.default(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG));
skillId = resources_config_1.default.getInstance().getSkillId(profile);
}
catch (err) {
throw new cli_error_1.default("Failed to read project resource file. " + "Please run the command within a ask-cli project.");
}
if (!stringUtils.isNonBlankString(skillId)) {
throw new cli_error_1.default("Failed to obtain skill-id from project " + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`);
}
return skillId;
}
async _dialogModeFactory(cmd) {
const config = await this._getDialogConfig(cmd);
if (config.replay) {
return new replay_mode_1.ReplayMode(config);
}
else if (config.evaluate) {
return new evaluate_mode_1.EvaluateMode({
...config,
view: (0, evaluate_view_1.createView)(this.messenger, config.verbose),
});
}
else {
return new interactive_mode_1.InteractiveMode(config);
}
}
_validateUserInputs(userInputs) {
return userInputs.map((input) => {
const trimmedInput = input.trim();
if (!stringUtils.isNonBlankString(trimmedInput)) {
throw new cli_error_1.default("Replay file's userInput cannot contain empty string.");
}
return trimmedInput;
});
}
}
exports.DialogCommand = DialogCommand;
exports.createCommand = new DialogCommand(new smapi_client_1.SmapiClientLateBound(), optionModel).createCommand();