UNPKG

4.7 kBJavaScriptView Raw
1const commander = require('commander');
2const { ModelIntrospector } = require('ask-smapi-sdk');
3const { kebabCase } = require('@src/utils/string-utils');
4const { CliCustomizationProcessor } = require('@src/commands/smapi/cli-customization-processor');
5const optionModel = require('@src/commands/option-model.json');
6const { smapiCommandHandler } = require('@src/commands/smapi/smapi-command-handler');
7const aliases = require('@src/commands/smapi/customizations/aliases.json');
8const { apiToCommanderMap } = require('@src/commands/smapi/customizations/parameters-map');
9
10const uploadCatalog = require('./appended-commands/upload-catalog');
11const exportPackage = require('./appended-commands/export-package');
12const getTask = require('./appended-commands/get-task');
13const searchTask = require('./appended-commands/search-task');
14
15
16const defaultOptions = [
17 {
18 flags: `-${optionModel.profile.alias}, --profile <profile>`,
19 description: optionModel.profile.description
20 },
21 {
22 flags: '--full-response',
23 description: optionModel['full-response'].description
24 },
25 {
26 flags: '--debug',
27 description: optionModel.debug.description
28 }
29];
30const requiredTemplate = { true: '[REQUIRED]', false: '[OPTIONAL]' };
31const jsonTemplate = { true: '[JSON]: JSON string or a file. Example: "$(cat {filePath})" '
32+ 'or "file:{filePath}", either absolute or relative path are supported.\n',
33false: '' };
34
35const _makeEnumTemplate = (param) => (param.enum ? `[ENUM]: ${param.enum.join()}.\n` : '');
36const _makeArrayTemplate = (param) => (param.isArray ? '[MULTIPLE]: Values can be separated by comma.\n' : '');
37
38const _makeAlias = (kebabName) => (aliases[kebabName] ? `-${aliases[kebabName]},` : '');
39
40const _makeOption = (param) => {
41 const name = apiToCommanderMap.get(param.name) || param.name;
42 const paramName = kebabCase(name);
43 const alias = _makeAlias(paramName);
44 const json = param.json || false;
45 const enumTemplate = _makeEnumTemplate(param);
46 const arrayTemplate = _makeArrayTemplate(param);
47 return {
48 name: `${alias}--${paramName} <${paramName}>`,
49 description:
50 (`${requiredTemplate[param.required]} ${(param.description || '').trim()} \n`
51 + `${arrayTemplate}`
52 + `${jsonTemplate[json]}`
53 + `${enumTemplate} `).trim()
54 };
55};
56/**
57 * Creates commander instance for Smapi operations.
58 */
59const makeSmapiCommander = () => {
60 const customizationProcessor = new CliCustomizationProcessor();
61 const modelIntrospector = new ModelIntrospector(null, customizationProcessor);
62 const operations = modelIntrospector.getOperations();
63
64 const program = new commander.Command();
65
66 let commanderInstance;
67
68 operations.forEach((operation, commandName) => {
69 const commanderToApiCustomizationMap = new Map();
70 const { apiOperationName, description } = operation;
71 commanderInstance = program
72 .command(commandName)
73 .description(description)
74 .storeOptionsAsProperties(false);
75 const { flatParamsMap } = operation.customizationMetadata;
76 flatParamsMap.forEach(param => {
77 const customizationValue = apiToCommanderMap.get(param.name);
78 if (customizationValue) {
79 commanderToApiCustomizationMap.set(customizationValue, param.name);
80 }
81 const option = _makeOption(param);
82 if (param.required) {
83 commanderInstance.requiredOption(option.name, option.description);
84 } else {
85 commanderInstance.option(option.name, option.description);
86 }
87 });
88
89 defaultOptions.forEach(option => {
90 commanderInstance.option(option.flags, option.description);
91 });
92 commanderInstance.action((inputCmdObj) => smapiCommandHandler(
93 apiOperationName,
94 flatParamsMap,
95 commanderToApiCustomizationMap,
96 inputCmdObj,
97 modelIntrospector
98 ));
99 });
100
101 // register hand-written appended commands
102 uploadCatalog.createCommand(program);
103 exportPackage.createCommand(program);
104 getTask.createCommand(program);
105 searchTask.createCommand(program);
106
107 program._name = 'ask smapi';
108 program
109 .description('The smapi command provides a number of sub-commands that '
110 + 'enable you to manage Alexa skills associated with your developer account.');
111
112 program.on('command:*', () => {
113 console.error(`Command not recognized. Please run "${program._name}" to check the user instructions.`);
114 process.exit(1);
115 });
116
117 return program;
118};
119
120module.exports = { makeSmapiCommander };