push neon reactor

This commit is contained in:
2026-07-12 15:11:38 +02:00
parent 172e72dbcd
commit aeab5f7820
9597 changed files with 2407488 additions and 0 deletions
@@ -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