ask-cli
Version:
Alexa Skills Kit (ASK) Command Line Interfaces
225 lines (224 loc) • 11.2 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.collectUserCreationProjectInfo = void 0;
const messenger_1 = __importDefault(require("../../view/messenger"));
const constants_1 = require("../../utils/constants");
const string_utils_1 = __importDefault(require("../../utils/string-utils"));
const url_utils_1 = __importDefault(require("../../utils/url-utils"));
const ui = __importStar(require("./ui"));
const template_helper_1 = require("./template-helper");
const prompt_view_1 = require("../../view/prompt-view");
const _1 = require(".");
const sample_template_1 = require("../../model/sample-template");
/**
* Ask for user input to create a project
* @param {Object} cmd command object
* @param {CollectUserCreationProjectInfoCallback} callback callback providing the NewSkillUserInput to the caller
*/
async function collectUserCreationProjectInfo(cmd, callback) {
var _a;
const userInput = {};
try {
// Make sure the arguments are valid
if (cmd.templateUrl && !url_utils_1.default.isValidUrl(cmd.templateUrl)) {
throw new Error(`The provided template url ${cmd.templateUrl} is not a valid url.`);
}
// gets the sample templates from S3
const sampleTemplates = [];
await (0, template_helper_1.getSampleTemplatesFromS3)(cmd.doDebug).then((fullSamples) => {
sampleTemplates.push(...fullSamples);
});
const sampleTemplateFilter = new sample_template_1.SampleTemplatesFilter(sampleTemplates);
// MODELING STACK TYPE
await promptForModelingStackType().then((modelingStack) => (userInput.modelingStack = modelingStack));
sampleTemplateFilter.filter("stack", (0, template_helper_1.convertUserInputToFilterValue)(userInput.modelingStack || _1.MODELING_STACK_IM));
// CODE LANGUAGE
// ignore when template url supplied
if (!cmd.templateUrl) {
await promptForCodeLanguage(sampleTemplateFilter.getSampleTemplates()).then((language) => (userInput.language = language));
sampleTemplateFilter.filter("lang", (0, template_helper_1.convertUserInputToFilterValue)(userInput.language || _1.CODE_LANGUAGE_NODEJS));
}
// DEPLOY TYPE
await promptForDeployerType(sampleTemplateFilter.getSampleTemplates()).then((deploymentType) => (userInput.deploymentType = deploymentType));
sampleTemplateFilter.filter("deploy", (0, template_helper_1.convertUserInputToFilterValue)(userInput.deploymentType || constants_1.DEPLOYER_TYPE.CFN.NAME));
if (userInput.deploymentType === constants_1.DEPLOYER_TYPE.HOSTED.NAME) {
// HOSTED SKILL LOCALE
// FIX hard coding until backend for hosted skills supports locales
userInput.locale = "en-US";
// HOSTED SKILL AWS REGION
await promptForSkillRegion().then((region) => (userInput.region = region));
}
else {
// NON HOSTED SKILL requires selecting a sample template from the list
// TEMPLATE INFO
await promptForTemplateInfo(cmd, sampleTemplateFilter.getSampleTemplates()).then((templateInfo) => (userInput.templateInfo = templateInfo));
}
// SKILL NAME
await promptForSkillName(((_a = userInput.templateInfo) === null || _a === void 0 ? void 0 : _a.templateUrl) || null).then((skillName) => (userInput.skillName = skillName));
// PROJECT FOLDER NAME
await promptForProjectFolderName(userInput.skillName || "").then((projectFolderName) => (userInput.projectFolderName = projectFolderName));
}
catch (e) {
callback(e, undefined);
return;
}
callback(null, userInput);
}
exports.collectUserCreationProjectInfo = collectUserCreationProjectInfo;
/**
* A Promise that fetches and returns the NewSkillCodeLanguage the user wants to leverage
*
* @param {SampleTemplate[]} samples remaining sample templates to select from
* @returns {Promise<NewSkillCodeLanguage>} a Promise that will provide a NewSkillCodeLanguage
*/
function promptForCodeLanguage(samples) {
return new Promise((resolve, reject) => {
const remainingLanguages = new Set(samples.map((sample) => {
switch (sample.lang) {
case "node":
return _1.CODE_LANGUAGE_NODEJS;
case "python":
return _1.CODE_LANGUAGE_PYTHON;
case "java":
return _1.CODE_LANGUAGE_JAVA;
}
}));
ui.selectSkillCodeLanguage(Array.from(remainingLanguages), (error, language) => (error ? reject(error) : resolve(language)));
});
}
/**
* A Promise that fetches and returns the NewSkillDeployerType the user wants to leverage
*
* @param {boolean} hasTemplateUrl true or false if the templateUrl was specified as a command line argument
* @returns {Promise<NewSkillDeployerType>} a Promise that will provide a NewSkillDeployerType
*/
function promptForDeployerType(samples) {
return new Promise((resolve, reject) => {
const remainingDeployerTypes = new Set(samples.map((sample) => {
switch (sample.deploy) {
case "lambda":
return constants_1.DEPLOYER_TYPE.LAMBDA;
case "cfn":
return constants_1.DEPLOYER_TYPE.CFN;
case "hosted":
return constants_1.DEPLOYER_TYPE.HOSTED;
case "self":
return constants_1.DEPLOYER_TYPE.SELF_HOSTED;
}
}));
ui.getDeploymentType(Array.from(remainingDeployerTypes), (error, deploymentType) => (error ? reject(error) : resolve(deploymentType)));
});
}
/**
* A Promise that fetches and returns the NewSkillModelingStackTypes the user wants the samples to use.
* i.e. interaction-model vs alexa-conversations
*
* @returns {Promise<NewSkillModelingStackTypes>} a Promise that will provide a Modeling Stack
*/
function promptForModelingStackType() {
return new Promise((resolve, reject) => {
ui.getModelingStackType((error, modelingStack) => (error ? reject(error) : resolve(modelingStack)));
});
}
/**
* A Promise that fetches and returns the default AWS Region to use for deploying the Alexa hosted skill
*
* @returns {Promise<NewSkillRegion>} Promises to return the default AWS Region the user wants to deploy the skill to
*/
function promptForSkillRegion() {
return new Promise((resolve, reject) => {
ui.getSkillDefaultRegion((error, region) => (error ? reject(error) : resolve(region)));
});
}
/**
* A Promise that fetches and returns a string specifying the new skill name to use.
*
* if a templateUrl is provided the user will be presented with a potentially better suited
* skill name default option instead of the generic hello world
*
* @param {string | null} templateUrl the template url to use for attempting to get a skillname instead of the default hello world
*/
function promptForSkillName(templateUrl) {
return new Promise((resolve, reject) => {
ui.getSkillName(templateUrl, (error, skillName) => (error ? reject(error) : resolve(skillName)));
});
}
/**
* A promise that fetches and returns a string specifying the new skill project folder name to use/create
*
* @param {string} skillName The name of the skill provided by the customer
* @returns {Promise<string>} Promises to return the customer provided input string specifying the new skill project folder name to use/create
*/
function promptForProjectFolderName(skillName) {
return new Promise((resolve, reject) => {
(0, prompt_view_1.getProjectFolderName)(string_utils_1.default.filterNonAlphanumeric(skillName), (error, folderName) => error ? reject(error) : resolve(folderName));
});
}
/**
* A Promise that fetches the NewSkillTemplateInfo for non-hosted skill
* also confirms download for non Alexa official git repos
*
* @param {Record<string, any>} cmd command object
* @param {SampleTemplate[]} samples the unfiltered skill samples templates to resolve
* @returns {Promise<NewSkillTemplateInfo>} a Promise that provides the New Skill Template Info <NewSkillTemplateInfo>
*/
async function promptForTemplateInfo(cmd, samples) {
return new Promise((resolve, reject) => {
if (!cmd.templateUrl) {
ui.getTargetTemplateName(samples, (err, sampleTemplate) => {
err
? reject(err)
: resolve({
templateUrl: sampleTemplate === null || sampleTemplate === void 0 ? void 0 : sampleTemplate.url,
templateName: sampleTemplate === null || sampleTemplate === void 0 ? void 0 : sampleTemplate.name,
templateBranch: sampleTemplate === null || sampleTemplate === void 0 ? void 0 : sampleTemplate.branch,
});
});
// handle when templateUrl is present in the the command line arguments
}
else {
const templateInfoFromCmd = {
templateUrl: cmd.templateUrl,
...(cmd.templateName ? { templateName: cmd.templateName } : {}),
...(cmd.templateBranch ? { templateBranch: cmd.templateBranch } : {}),
};
// no warnings/confirmation of download required for official alexa templates
if (url_utils_1.default.isUrlOfficialTemplate(cmd.templateUrl)) {
resolve(templateInfoFromCmd);
}
else {
messenger_1.default.getInstance().warn(`CLI is about to download the skill template from unofficial template ${cmd.templateUrl}. ` +
"Please make sure you understand the source code to best protect yourself from malicious usage.");
ui.confirmUsingUnofficialTemplate((confirmErr, confirmResult) => {
confirmErr || !confirmResult ? reject(confirmErr) : resolve(templateInfoFromCmd);
});
}
}
});
}