push neon reactor
This commit is contained in:
Generated
Vendored
+247
@@ -0,0 +1,247 @@
|
||||
/*!
|
||||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*/
|
||||
import { initializePlayerServices, updateEnvironmentName, updateRegion, } from '@microsoft/power-apps-actions';
|
||||
import { Command } from 'commander';
|
||||
import packageJson from '../package.json' with { type: 'json' };
|
||||
import { getSettings } from './CliSettings.js';
|
||||
import { createDefaultStringOption } from './CliUtils.js';
|
||||
import { HelpStrings } from './Constants/HelpStrings.js';
|
||||
import { UsageError } from './Errors/CliError.js';
|
||||
import { buildVerbDescriptionTable } from './Utils/BuildVerbDescriptionTable.js';
|
||||
import { GlobalArguments } from './Verbs/VerbConstants.js';
|
||||
export class ArgumentProvider {
|
||||
_httpClient;
|
||||
_logger;
|
||||
_authenticationProvider;
|
||||
_environmentId;
|
||||
_region;
|
||||
_verb;
|
||||
_program;
|
||||
_options = {};
|
||||
constructor(_httpClient, _logger, _authenticationProvider) {
|
||||
this._httpClient = _httpClient;
|
||||
this._logger = _logger;
|
||||
this._authenticationProvider = _authenticationProvider;
|
||||
this._verb = (process.argv[2] || process.env.VERB);
|
||||
this._program = new Command();
|
||||
// Add the --non-interactive switch as a global option
|
||||
this._program.option('--non-interactive', 'Run in non-interactive mode (no prompts, all parameters must be provided via flags or environment variables)');
|
||||
this._program.option('--json', 'Format output as JSON');
|
||||
this._program.option('--no-color', 'Disable colored output');
|
||||
// If a specific verb is detected (and it's not a flag like --help), we configure the program
|
||||
// to behave as if that verb is the command itself (e.g., "power-apps-cli add-data-source").
|
||||
// This allows us to display help specific to that verb (options, description) when --help is used,
|
||||
// rather than showing the generic top-level help. We omit the [verb] argument definition here
|
||||
// because the verb is already "consumed" into the program name for this execution context.
|
||||
if (this._verb && !this._verb.startsWith('-')) {
|
||||
this._program.name(`power-apps ${this._verb}`);
|
||||
}
|
||||
else {
|
||||
this._program.name('power-apps');
|
||||
this._program.usage('[option] [command] [<args>]');
|
||||
}
|
||||
this._program.version(packageJson.version, '-v, --version', 'output the current version');
|
||||
this._program.description(HelpStrings.Global.ProgramDescription);
|
||||
// Register custom help text to show verb table on global --help
|
||||
// This uses Commander's addHelpText hook which runs when help is displayed
|
||||
this._program.addHelpText('after', (_context) => {
|
||||
// Only show verb table for global help (not verb-specific help)
|
||||
if (!this._verb || this._verb.startsWith('-')) {
|
||||
return '\n' + buildVerbDescriptionTable() + '\n';
|
||||
}
|
||||
return '';
|
||||
});
|
||||
const settings = getSettings();
|
||||
this._environmentId = settings.appConfig?.environmentId;
|
||||
this._region = settings.appConfig?.region;
|
||||
if (!this._region) {
|
||||
// Do not provide a prompt, default to prod
|
||||
this.addOption({
|
||||
flags: {
|
||||
key: GlobalArguments.Cloud.name,
|
||||
},
|
||||
env: GlobalArguments.Cloud.envVar,
|
||||
default: 'prod',
|
||||
description: HelpStrings.Global.Cloud,
|
||||
});
|
||||
}
|
||||
// If we do not have an environmentId, add an option to get one
|
||||
if (!this._environmentId) {
|
||||
this.addOption(createDefaultStringOption({
|
||||
flags: {
|
||||
key: GlobalArguments.EnvironmentId.name,
|
||||
alias: GlobalArguments.EnvironmentId.alias,
|
||||
},
|
||||
env: GlobalArguments.EnvironmentId.envVar,
|
||||
message: 'Please provide the environment ID:',
|
||||
description: HelpStrings.Global.EnvironmentId,
|
||||
}));
|
||||
}
|
||||
initializePlayerServices({
|
||||
httpClient: this._httpClient,
|
||||
logger: this._logger,
|
||||
// Default region is 'prod' if not specified
|
||||
region: this._region || 'prod',
|
||||
// Do a temporary variable
|
||||
environmentName: this._environmentId || 'default',
|
||||
});
|
||||
}
|
||||
addSwitch(cliOption) {
|
||||
this._createOption(cliOption, false);
|
||||
}
|
||||
addSwitches(cliOptions) {
|
||||
cliOptions.forEach((cliOption) => this._createOption(cliOption, false));
|
||||
}
|
||||
addOption(cliOption) {
|
||||
this._createOption(cliOption);
|
||||
}
|
||||
addOptions(cliOptions) {
|
||||
cliOptions.forEach((cliOption) => this._createOption(cliOption));
|
||||
}
|
||||
async runVerb() {
|
||||
// Commander needs to see only the verb-specific arguments, so strip the verb token
|
||||
// when a verb was supplied explicitly; global flag paths skip this method entirely.
|
||||
if (this._verb && !this._verb.startsWith('-') && process.argv[2] === this._verb) {
|
||||
const args = [process.argv[0], process.argv[1], ...process.argv.slice(3)];
|
||||
this._program.parse(args);
|
||||
}
|
||||
else {
|
||||
this._program.parse();
|
||||
}
|
||||
await this._getRequiredVariables();
|
||||
if (!this._region) {
|
||||
throw new UsageError('Region is not set. Use --cloud or set the CLOUD_INSTANCE environment variable.');
|
||||
}
|
||||
await this._authenticationProvider.initAsync(this._region);
|
||||
await this._logger.initializeTelemetry(this._authenticationProvider);
|
||||
this._logger.trackActivityEvent('Initialize', {
|
||||
verb: this._verb,
|
||||
});
|
||||
}
|
||||
// Handles scenarios where only global flags (e.g., --help/--version) are provided.
|
||||
// Returns 'help' when no verb is present, 'flag' when a flag verb needs Commander handling,
|
||||
// and 'none' when execution should continue to verb-specific logic.
|
||||
handleGlobalHelpOrFlagsAndExit() {
|
||||
if (!this._verb) {
|
||||
this._program.help(); // This will display help and exit
|
||||
}
|
||||
if (this._verb.startsWith('-')) {
|
||||
this._program.parse(process.argv);
|
||||
}
|
||||
}
|
||||
getVerb() {
|
||||
if (!this._verb || this._verb.startsWith('-')) {
|
||||
throw new UsageError('No command specified. Run "power-apps --help" for available commands.');
|
||||
}
|
||||
return this._verb;
|
||||
}
|
||||
async getOption(key, ignorePrompt) {
|
||||
const settings = getSettings();
|
||||
let value = this._program.getOptionValue(key);
|
||||
const option = this._options[key];
|
||||
// Fallback to environment variable if not provided via CLI
|
||||
if (value === undefined && option && option.env) {
|
||||
value = process.env[option.env];
|
||||
}
|
||||
// Fallback to default value if not provided via CLI or Env
|
||||
if (value === undefined && option && option.default !== undefined) {
|
||||
value = option.default;
|
||||
}
|
||||
if (!value && !ignorePrompt && option?.customPrompt) {
|
||||
if (!settings.interactive) {
|
||||
if (option.optionalInNonInteractive) {
|
||||
// Option is optional — return undefined and let the actions layer handle it.
|
||||
}
|
||||
else {
|
||||
const flagName = option.flags.key;
|
||||
const alias = option.flags.alias;
|
||||
const flagHint = alias ? `--${flagName} (-${alias})` : `--${flagName}`;
|
||||
const envHint = option.env ? ` or environment variable (${option.env})` : '';
|
||||
throw new UsageError(`Missing required option ${flagHint}${envHint}. In non-interactive mode, all parameters must be provided via flags or environment variables.`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = await option.customPrompt();
|
||||
}
|
||||
}
|
||||
// Option could be undefined by design, so just return it.
|
||||
return value;
|
||||
}
|
||||
getAuthenticationProvider() {
|
||||
return this._authenticationProvider;
|
||||
}
|
||||
/**
|
||||
* Sets the description for the current command context.
|
||||
* This is used to display help information specific to the verb being executed.
|
||||
*
|
||||
* @param {string} description - The description to set for the program.
|
||||
*/
|
||||
setDescription(description) {
|
||||
this._program.description(description);
|
||||
}
|
||||
isJsonMode() {
|
||||
return this._program.opts().json === true;
|
||||
}
|
||||
addExamples(examples) {
|
||||
if (!examples || examples.length === 0)
|
||||
return;
|
||||
this._program.addHelpText('after', () => {
|
||||
const lines = ['', 'Examples:'];
|
||||
examples.forEach((example) => {
|
||||
lines.push(` $ ${example}`);
|
||||
});
|
||||
return lines.join('\n');
|
||||
});
|
||||
}
|
||||
getEnvironmentId() {
|
||||
return this._environmentId;
|
||||
}
|
||||
async _getRequiredVariables() {
|
||||
// We always need a region and environmentId, which we usually get from the config.
|
||||
// If there is no config we prompt for them, except for init/telemetry which manage their own state.
|
||||
if (this._verb !== 'telemetry' && this._verb !== 'logout') {
|
||||
if (!this._environmentId) {
|
||||
const environmentId = await this.getOption('environmentId');
|
||||
if (environmentId) {
|
||||
this._environmentId = environmentId;
|
||||
updateEnvironmentName(this._environmentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this._region) {
|
||||
const region = await this.getOption('cloud');
|
||||
if (region) {
|
||||
this._region = region;
|
||||
updateRegion(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {CliOption} cliOption
|
||||
* @param {boolean} [hasValue=true] true if the option requires a value, false for a switch such as --help
|
||||
*/
|
||||
_createOption(cliOption, hasValue = true) {
|
||||
const option = this._program.createOption(hasValue ? this._createFlags(cliOption.flags) : this._createSwitchFlags(cliOption.flags), cliOption.description);
|
||||
// We do not set the env or default here because we want to handle it manually in getOption
|
||||
// This allows us to hide the env variable from the help text
|
||||
// Hide global options from help output when showing global help
|
||||
// This prevents --environment-id and --cloud from showing up in the global help
|
||||
if (!this._verb || this._verb.startsWith('-')) {
|
||||
option.hideHelp();
|
||||
}
|
||||
this._program.addOption(option);
|
||||
// Map to CliOption using Commander's camelCase attribute name so
|
||||
// getOption('environmentId') finds the option registered as --environment-id.
|
||||
this._options[option.attributeName()] = cliOption;
|
||||
}
|
||||
_createFlags(flags) {
|
||||
const { key, alias } = flags;
|
||||
return alias ? `-${alias}, --${key} <${key}>` : `--${key} <${key}>`;
|
||||
}
|
||||
_createSwitchFlags(flags) {
|
||||
const { key, alias } = flags;
|
||||
return alias ? `-${alias}, --${key}` : `--${key}`;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=ArgumentProvider.js.map
|
||||
Reference in New Issue
Block a user