mirror of
https://github.com/serverless/serverless.git
synced 2025-12-08 19:46:03 +00:00
104 lines
3.6 KiB
JavaScript
104 lines
3.6 KiB
JavaScript
// CLI params parser, to be used before we have deducted what commands and options are supported in given context
|
|
|
|
'use strict';
|
|
|
|
const ensureMap = require('type/map/ensure');
|
|
const memoizee = require('memoizee');
|
|
const parseArgs = require('./parse-args');
|
|
|
|
const baseArgsSchema = {
|
|
boolean: new Set(['help', 'help-interactive', 'use-local-credentials', 'v', 'version']),
|
|
string: new Set(['app', 'config', 'org', 'stage']),
|
|
alias: new Map([
|
|
['c', 'config'],
|
|
['h', 'help'],
|
|
]),
|
|
};
|
|
|
|
const resolveArgsSchema = (commandOptionsSchema) => {
|
|
const options = { boolean: new Set(), string: new Set(), alias: new Map(), multiple: new Set() };
|
|
for (const [name, optionSchema] of Object.entries(commandOptionsSchema)) {
|
|
switch (optionSchema.type) {
|
|
case 'boolean':
|
|
options.boolean.add(name);
|
|
break;
|
|
case 'multiple':
|
|
options.multiple.add(name);
|
|
break;
|
|
case 'string':
|
|
options.string.add(name);
|
|
break;
|
|
default:
|
|
}
|
|
if (optionSchema.shortcut) options.alias.set(optionSchema.shortcut, name);
|
|
}
|
|
return options;
|
|
};
|
|
|
|
module.exports = memoizee((commandsSchema = require('./commands-schema')) => {
|
|
commandsSchema = ensureMap(commandsSchema);
|
|
const args = process.argv.slice(2);
|
|
|
|
// Ideally no options should be passed before command (to know what options are supported,
|
|
// and whether they're boolean or not, we need to know command name upfront).
|
|
// Still so far we (kind of) supported such notation and we need to maintain it in current major.
|
|
// Thefore at first resolution stage we use schema that recognizes just some popular options
|
|
let options = parseArgs(args, baseArgsSchema);
|
|
let commands = options._;
|
|
delete options._;
|
|
|
|
let command = commands.join(' ');
|
|
|
|
// Having command potentially resolved, resolve options again with help of the command schema
|
|
let commandSchema = commandsSchema.get(command);
|
|
while (commandSchema) {
|
|
const resolvedOptions = parseArgs(args, resolveArgsSchema(commandSchema.options));
|
|
const resolvedCommand = resolvedOptions._.join(' ');
|
|
if (resolvedCommand === command) {
|
|
options = resolvedOptions;
|
|
commands = options._;
|
|
delete options._;
|
|
break;
|
|
}
|
|
// Unlikely scenario, where after applying the command schema different command resolves
|
|
// It can happen only in cases where e.g. for "sls deploy --force function -f foo"
|
|
// we intially assume "deploy" command, while after applying "deploy" command schema it's
|
|
// actually a "deploy function" command that resolves
|
|
command = resolvedCommand;
|
|
commandSchema = commandsSchema.get(resolvedCommand);
|
|
}
|
|
|
|
const result = { commands, options, command, commandSchema, commandsSchema };
|
|
if (!commandSchema) {
|
|
result.isContainerCommand = Array.from(commandsSchema.keys()).some((commandName) =>
|
|
commandName.startsWith(`${command} `)
|
|
);
|
|
if (result.isContainerCommand) {
|
|
result.isHelpRequest = true;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (
|
|
(!command && options['help-interactive']) ||
|
|
options.help ||
|
|
options.version ||
|
|
command === 'help'
|
|
) {
|
|
result.isHelpRequest = true;
|
|
return result;
|
|
}
|
|
|
|
const argsString = args.join(' ');
|
|
if (command && argsString !== command && !argsString.startsWith(`${command} `)) {
|
|
// Some options were passed before command name (e.g. "sls -v deploy"), deprecate such usage
|
|
require('../utils/logDeprecation')(
|
|
'CLI_OPTIONS_BEFORE_COMMAND',
|
|
'"serverless" command options are expected to follow command and not be put before the command.\n' +
|
|
'Starting from next major Serverless will no longer support the latter form.'
|
|
);
|
|
}
|
|
|
|
return result;
|
|
});
|