#!/usr/bin/env node
import * as path from 'path';
import * as dotenv from 'dotenv';
import './utils/assert-node-version';
import * as yargs from 'yargs';
import * as colors from 'colorette';
import { outputExtensions, regionChoices } from './types';
import { previewDocs } from './commands/preview-docs';
import { handleStats } from './commands/stats';
import { handleSplit } from './commands/split';
import { handleJoin } from './commands/join';
import { handlePushStatus } from './reunite/commands/push-status';
import { handleLint } from './commands/lint';
import { handleBundle } from './commands/bundle';
import { handleLogin, handleLogout } from './commands/auth';
import { handlerBuildCommand } from './commands/build-docs';
import {
  cacheLatestVersion,
  notifyUpdateCliVersion,
  version,
} from './utils/update-version-notifier';
import { commandWrapper } from './wrapper';
import { previewProject } from './commands/preview-project';
import { handleTranslations } from './commands/translations';
import { handleEject } from './commands/eject';
import { PRODUCT_PLANS } from './commands/preview-project/constants';
import { commonPushHandler } from './commands/push';

import type { Arguments } from 'yargs';
import type { OutputFormat, RuleSeverity } from '@redocly/openapi-core';
import type { GenerateArazzoFileOptions, RespectOptions } from '@redocly/respect-core';
import type { BuildDocsArgv } from './commands/build-docs/types';
import type { PushStatusOptions } from './reunite/commands/push-status';
import type { PushArguments } from './types';
import type { EjectOptions } from './commands/eject';

dotenv.config({ path: path.resolve(process.cwd(), './.env') });

if (!('replaceAll' in String.prototype)) {
  require('core-js/actual/string/replace-all');
}

cacheLatestVersion();

yargs
  .version('version', 'Show version number.', version)
  .help('help', 'Show help.')
  .parserConfiguration({ 'greedy-arrays': false, 'camel-case-expansion': false })
  .command(
    'stats [api]',
    'Show statistics for an API description.',
    (yargs) =>
      yargs.positional('api', { type: 'string' }).option({
        config: { description: 'Path to the config file.', type: 'string' },
        'lint-config': {
          description: 'Severity level for config file linting.',
          choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
          default: 'warn' as RuleSeverity,
        },
        format: {
          description: 'Use a specific output format.',
          choices: ['stylish', 'json', 'markdown'] as ReadonlyArray<OutputFormat>,
          default: 'stylish' as OutputFormat,
        },
      }),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'stats';
      commandWrapper(handleStats)(argv);
    }
  )
  .command(
    'split [api]',
    'Split an API description into a multi-file structure.',
    (yargs) =>
      yargs
        .positional('api', {
          description: 'API description file that you want to split',
          type: 'string',
        })
        .option({
          outDir: {
            description: 'Output directory where files will be saved.',
            required: true,
            type: 'string',
          },
          separator: {
            description: 'File path separator used while splitting.',
            required: false,
            type: 'string',
            default: '_',
          },
          config: {
            description: 'Path to the config file.',
            requiresArg: true,
            type: 'string',
          },
          'lint-config': {
            description: 'Severity level for config file linting.',
            choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
            default: 'warn' as RuleSeverity,
          },
        })
        .demandOption('api'),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'split';
      commandWrapper(handleSplit)(argv);
    }
  )
  .command(
    'join [apis...]',
    'Join multiple API descriptions into one [experimental].',
    (yargs) =>
      yargs
        .positional('apis', {
          array: true,
          type: 'string',
          demandOption: true,
        })
        .option({
          'prefix-tags-with-info-prop': {
            description: 'Prefix tags with property value from info object.',
            requiresArg: true,
            type: 'string',
          },
          'prefix-tags-with-filename': {
            description: 'Prefix tags with property value from file name.',
            type: 'boolean',
            default: false,
          },
          'prefix-components-with-info-prop': {
            description: 'Prefix components with property value from info object.',
            requiresArg: true,
            type: 'string',
          },
          'without-x-tag-groups': {
            description: 'Skip automated x-tagGroups creation',
            type: 'boolean',
          },
          output: {
            description: 'Output file.',
            alias: 'o',
            type: 'string',
          },
          config: {
            description: 'Path to the config file.',
            requiresArg: true,
            type: 'string',
          },
          'lint-config': {
            description: 'Severity level for config file linting.',
            choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
            default: 'warn' as RuleSeverity,
          },
          lint: {
            hidden: true,
            deprecated: true,
          },
          decorate: {
            hidden: true,
            deprecated: true,
          },
          preprocess: {
            hidden: true,
            deprecated: true,
          },
        }),
    (argv) => {
      const DEPRECATED_OPTIONS = ['lint', 'preprocess', 'decorate'];
      const DECORATORS_DOCUMENTATION_LINK = 'https://redocly.com/docs/cli/decorators/#decorators';
      const JOIN_COMMAND_DOCUMENTATION_LINK = 'https://redocly.com/docs/cli/commands/join/#join';

      DEPRECATED_OPTIONS.forEach((option) => {
        if (argv[option]) {
          process.stdout.write(
            `${colors.red(
              `Option --${option} is no longer supported. Please review join command documentation ${JOIN_COMMAND_DOCUMENTATION_LINK}.`
            )}`
          );
          process.stdout.write('\n\n');

          if (['preprocess', 'decorate'].includes(option)) {
            process.stdout.write(
              `${colors.red(
                `If you are looking for decorators, please review the decorators documentation ${DECORATORS_DOCUMENTATION_LINK}.`
              )}`
            );
            process.stdout.write('\n\n');
          }

          yargs.showHelp();
          process.exit(1);
        }
      });

      process.env.REDOCLY_CLI_COMMAND = 'join';
      commandWrapper(handleJoin)(argv);
    }
  )
  .command(
    'push-status [pushId]',
    false,
    (yargs) =>
      yargs
        .positional('pushId', {
          description: 'Push id.',
          type: 'string',
          required: true,
        })
        .implies('max-execution-time', 'wait')
        .option({
          organization: {
            description: 'Name of the organization to push to.',
            type: 'string',
            alias: 'o',
          },
          project: {
            description: 'Name of the project to push to.',
            type: 'string',
            required: true,
            alias: 'p',
          },
          domain: { description: 'Specify a domain.', alias: 'd', type: 'string', required: false },
          wait: {
            description: 'Wait for build to finish.',
            type: 'boolean',
            default: false,
          },
          'max-execution-time': {
            description: 'Maximum execution time in seconds.',
            type: 'number',
          },
          'continue-on-deploy-failures': {
            description: 'Command does not fail even if the deployment fails.',
            type: 'boolean',
            default: false,
          },
          'lint-config': {
            description: 'Severity level for config file linting.',
            choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
            default: 'warn' as RuleSeverity,
          },
        }),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'push-status';
      commandWrapper(handlePushStatus)(argv as Arguments<PushStatusOptions>);
    }
  )
  .command(
    'push [apis...]',
    'Push an API description to the Redocly API registry.',
    (yargs) =>
      yargs
        .positional('apis', {
          type: 'string',
          array: true,
          required: true,
          default: [],
        })
        .hide('project')
        .hide('domain')
        .hide('mount-path')
        .hide('author')
        .hide('message')
        .hide('default-branch')
        .hide('verbose')
        .hide('commit-sha')
        .hide('commit-url')
        .hide('namespace')
        .hide('repository')
        .hide('wait-for-deployment')
        .hide('created-at')
        .hide('max-execution-time')
        .deprecateOption('batch-id', 'use --job-id')
        .implies('job-id', 'batch-size')
        .implies('batch-id', 'batch-size')
        .implies('batch-size', 'job-id')
        .implies('max-execution-time', 'wait-for-deployment')
        .option({
          destination: {
            description: 'API name and version in the format `name@version`.',
            type: 'string',
            alias: 'd',
          },
          branch: {
            description: 'Branch name to push to.',
            type: 'string',
            alias: 'b',
          },
          upsert: {
            description:
              "Create the specified API version if it doesn't exist, update if it does exist.",
            type: 'boolean',
            alias: 'u',
          },
          'batch-id': {
            description:
              'Specifies the ID of the CI job that the current push will be associated with.',
            type: 'string',
            requiresArg: true,
            deprecated: true,
            hidden: true,
          },
          'job-id': {
            description: 'ID of the CI job that the current push will be associated with.',
            type: 'string',
            requiresArg: true,
          },
          'batch-size': {
            description: 'Number of CI pushes to expect in a batch.',
            type: 'number',
            requiresArg: true,
          },
          region: { description: 'Specify a region.', alias: 'r', choices: regionChoices },
          'skip-decorator': {
            description: 'Ignore certain decorators.',
            array: true,
            type: 'string',
          },
          public: {
            description: 'Make the API description available to the public',
            type: 'boolean',
          },
          files: {
            description: 'List of other folders and files to upload',
            array: true,
            type: 'string',
          },
          'lint-config': {
            description: 'Severity level for config file linting.',
            choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
            default: 'warn' as RuleSeverity,
          },
          organization: {
            description: 'Name of the organization to push to.',
            type: 'string',
            alias: 'o',
          },
          project: {
            description: 'Name of the project to push to.',
            type: 'string',
            alias: 'p',
          },
          'mount-path': {
            description: 'The path files should be pushed to.',
            type: 'string',
            alias: 'mp',
          },
          author: {
            description: 'Author of the commit.',
            type: 'string',
            alias: 'a',
          },
          message: {
            description: 'Commit message.',
            type: 'string',
            alias: 'm',
          },
          'commit-sha': {
            description: 'Commit SHA.',
            type: 'string',
            alias: 'sha',
          },
          'commit-url': {
            description: 'Commit URL.',
            type: 'string',
            alias: 'url',
          },
          namespace: {
            description: 'Repository namespace.',
            type: 'string',
          },
          repository: {
            description: 'Repository name.',
            type: 'string',
          },
          'created-at': {
            description: 'Commit creation date.',
            type: 'string',
          },
          domain: { description: 'Specify a domain.', alias: 'd', type: 'string' },
          config: {
            description: 'Path to the config file.',
            requiresArg: true,
            type: 'string',
          },
          'default-branch': {
            type: 'string',
            default: 'main',
          },
          'max-execution-time': {
            description: 'Maximum execution time in seconds.',
            type: 'number',
          },
          'wait-for-deployment': {
            description: 'Wait for build to finish.',
            type: 'boolean',
            default: false,
          },
          verbose: {
            type: 'boolean',
            default: false,
          },
          'continue-on-deploy-failures': {
            description: 'Command does not fail even if the deployment fails.',
            type: 'boolean',
            default: false,
          },
        }),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'push';
      commandWrapper(commonPushHandler(argv))(argv as Arguments<PushArguments>);
    }
  )
  .command(
    'lint [apis...]',
    'Lint an API or Arazzo description.',
    (yargs) =>
      yargs.positional('apis', { array: true, type: 'string', demandOption: true }).option({
        format: {
          description: 'Use a specific output format.',
          choices: [
            'stylish',
            'codeframe',
            'json',
            'checkstyle',
            'codeclimate',
            'summary',
            'markdown',
            'github-actions',
          ] as ReadonlyArray<OutputFormat>,
          default: 'codeframe' as OutputFormat,
        },
        'max-problems': {
          requiresArg: true,
          description: 'Reduce output to a maximum of N problems.',
          type: 'number',
          default: 100,
        },
        'generate-ignore-file': {
          description: 'Generate an ignore file.',
          type: 'boolean',
        },
        'skip-rule': {
          description: 'Ignore certain rules.',
          array: true,
          type: 'string',
        },
        'skip-preprocessor': {
          description: 'Ignore certain preprocessors.',
          array: true,
          type: 'string',
        },
        'lint-config': {
          description: 'Severity level for config file linting.',
          choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
          default: 'warn' as RuleSeverity,
        },
        config: {
          description: 'Path to the config file.',
          requiresArg: true,
          type: 'string',
        },
        extends: {
          description: 'Override extends configurations (defaults or config file settings).',
          requiresArg: true,
          array: true,
          type: 'string',
        },
      }),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'lint';
      commandWrapper(handleLint)(argv);
    }
  )
  .command(
    'bundle [apis...]',
    'Bundle a multi-file API description to a single file.',
    (yargs) =>
      yargs
        .positional('apis', { array: true, type: 'string', demandOption: true })
        .options({
          output: {
            type: 'string',
            description: 'Output file or folder for inline APIs.',
            alias: 'o',
          },
          ext: {
            description: 'Bundle file extension.',
            requiresArg: true,
            choices: outputExtensions,
          },
          'skip-preprocessor': {
            description: 'Ignore certain preprocessors.',
            array: true,
            type: 'string',
          },
          'skip-decorator': {
            description: 'Ignore certain decorators.',
            array: true,
            type: 'string',
          },
          dereferenced: {
            alias: 'd',
            type: 'boolean',
            description: 'Produce a fully dereferenced bundle.',
          },
          force: {
            alias: 'f',
            type: 'boolean',
            description: 'Produce bundle output even when errors occur.',
          },
          config: {
            description: 'Path to the config file.',
            type: 'string',
          },
          metafile: {
            description: 'Produce metadata about the bundle',
            type: 'string',
          },
          extends: {
            description: 'Override extends configurations (defaults or config file settings).',
            requiresArg: true,
            array: true,
            type: 'string',
            hidden: true,
          },
          'remove-unused-components': {
            description: 'Remove unused components.',
            type: 'boolean',
            default: false,
          },
          'keep-url-references': {
            description: 'Keep absolute url references.',
            type: 'boolean',
            alias: 'k',
          },
          'lint-config': {
            description: 'Severity level for config file linting.',
            choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
            default: 'warn' as RuleSeverity,
          },
          format: {
            hidden: true,
            deprecated: true,
          },
          lint: {
            hidden: true,
            deprecated: true,
          },
          'skip-rule': {
            hidden: true,
            deprecated: true,
            array: true,
            type: 'string',
          },
          'max-problems': {
            hidden: true,
            deprecated: true,
          },
        })
        .check((argv) => {
          if (argv.output && (!argv.apis || argv.apis.length === 0)) {
            throw new Error('At least one inline API must be specified when using --output.');
          }
          return true;
        }),
    (argv) => {
      const DEPRECATED_OPTIONS = ['lint', 'format', 'skip-rule', 'max-problems'];
      const LINT_AND_BUNDLE_DOCUMENTATION_LINK =
        'https://redocly.com/docs/cli/guides/lint-and-bundle/#lint-and-bundle-api-descriptions-with-redocly-cli';

      DEPRECATED_OPTIONS.forEach((option) => {
        if (argv[option]) {
          process.stdout.write(
            `${colors.red(
              `Option --${option} is no longer supported. Please use separate commands, as described in the ${LINT_AND_BUNDLE_DOCUMENTATION_LINK}.`
            )}`
          );
          process.stdout.write('\n\n');
          yargs.showHelp();
          process.exit(1);
        }
      });

      process.env.REDOCLY_CLI_COMMAND = 'bundle';
      commandWrapper(handleBundle)(argv);
    }
  )
  .command(
    'check-config',
    'Lint the Redocly configuration file.',
    async (yargs) =>
      yargs.option({
        config: {
          description: 'Path to the config file.',
          type: 'string',
        },
        'lint-config': {
          description: 'Severity level for config file linting.',
          choices: ['warn', 'error'] as ReadonlyArray<RuleSeverity>,
          default: 'error' as RuleSeverity,
        },
      }),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'check-config';
      commandWrapper()(argv);
    }
  )
  .command(
    'login',
    'Log in to Redocly.',
    async (yargs) =>
      yargs.options({
        verbose: {
          description: 'Include additional output.',
          type: 'boolean',
        },
        residency: {
          description: 'Residency of the application. Defaults to `us`.',
          alias: ['r', 'region'],
          type: 'string',
        },
        config: {
          description: 'Path to the config file.',
          requiresArg: true,
          type: 'string',
        },
        next: {
          description: 'Use Reunite application to login.',
          type: 'boolean',
        },
      }),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'login';
      commandWrapper(handleLogin)(argv);
    }
  )
  .command(
    'logout',
    'Clear your stored credentials for the Redocly API registry.',
    (yargs) => yargs,
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'logout';
      commandWrapper(handleLogout)(argv);
    }
  )
  .command(
    'preview',
    'Preview Redocly project using one of the product NPM packages.',
    (yargs) =>
      yargs.options({
        product: {
          type: 'string',
          choices: ['redoc', 'revel', 'reef', 'realm', 'redoc-revel', 'redoc-reef', 'revel-reef'],
          description:
            "Product used to launch preview. Default is inferred from project's package.json or 'realm' is used.",
        },
        plan: {
          type: 'string',
          choices: PRODUCT_PLANS,
          default: 'enterprise',
        },
        port: {
          alias: 'p',
          type: 'number',
          description: 'Preview port.',
          default: 4000,
        },
        'project-dir': {
          alias: ['d', 'source-dir'],
          type: 'string',
          description:
            'Specifies the project content directory. The default value is the directory where the command is executed.',
          default: '.',
        },
        'lint-config': {
          description: 'Severity level for config file linting.',
          choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
          default: 'warn' as RuleSeverity,
        },
      }),
    (argv) => {
      if (process.argv.some((arg) => arg.startsWith('--source-dir'))) {
        process.stderr.write(
          colors.red(
            'Option --source-dir is deprecated and will be removed soon. Use --project-dir instead.\n'
          )
        );
      }
      commandWrapper(previewProject)(argv);
    }
  )
  .command(
    'preview-docs [api]',
    'Preview API reference docs for an API description.',
    (yargs) =>
      yargs.positional('api', { type: 'string' }).options({
        port: {
          alias: 'p',
          type: 'number',
          default: 8080,
          description: 'Preview port.',
        },
        host: {
          alias: 'h',
          type: 'string',
          default: '127.0.0.1',
          description: 'Preview host.',
        },
        'skip-preprocessor': {
          description: 'Ignore certain preprocessors.',
          array: true,
          type: 'string',
        },
        'skip-decorator': {
          description: 'Ignore certain decorators.',
          array: true,
          type: 'string',
        },
        'use-community-edition': {
          description: 'Use Redoc CE for documentation preview.',
          type: 'boolean',
        },
        force: {
          alias: 'f',
          type: 'boolean',
          description: 'Produce bundle output even when errors occur.',
        },
        config: {
          description: 'Path to the config file.',
          type: 'string',
        },
        'lint-config': {
          description: 'Severity level for config file linting.',
          choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
          default: 'warn' as RuleSeverity,
        },
      }),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'preview-docs';
      commandWrapper(previewDocs)(argv);
    }
  )
  .command(
    'build-docs [api]',
    'Produce API documentation as an HTML file',
    (yargs) =>
      yargs
        .positional('api', { type: 'string' })
        .options({
          o: {
            describe: 'Output destination file.',
            alias: 'output',
            type: 'string',
            default: 'redoc-static.html',
          },
          title: {
            describe: 'Page title.',
            type: 'string',
          },
          disableGoogleFont: {
            describe: 'Disable Google fonts.',
            type: 'boolean',
            default: false,
          },
          t: {
            alias: 'template',
            describe:
              'Path to handlebars page template, see https://github.com/Redocly/redocly-cli/blob/main/packages/cli/src/commands/build-docs/template.hbs for the example.',
            type: 'string',
          },
          templateOptions: {
            describe:
              'Additional options to pass to the template. Use dot notation, e.g. templateOptions.metaDescription',
          },
          theme: {
            describe:
              'Redoc theme.openapi configuration. Use dot notation, e.g. theme.openapi.nativeScrollbars',
          },
          config: {
            describe: 'Path to the config file.',
            type: 'string',
          },
          'lint-config': {
            description: 'Severity level for config file linting.',
            choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
            default: 'warn' as RuleSeverity,
          },
        })
        .check((argv: any) => {
          if (argv.theme && !argv.theme?.openapi)
            throw Error('Invalid option: theme.openapi not set.');
          return true;
        }),
    async (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'build-docs';
      commandWrapper(handlerBuildCommand)(argv as Arguments<BuildDocsArgv>);
    }
  )
  .command(
    'translate <locale>',
    'Creates or updates translations.yaml files and fills them with missing built-in translations and translations from the redocly.yaml and sidebars.yaml files.',
    (yargs) =>
      yargs
        .positional('locale', {
          description:
            'Locale code to generate translations for, or `all` for all current project locales.',
          type: 'string',
          demandOption: true,
        })
        .options({
          'project-dir': {
            alias: 'd',
            type: 'string',
            description:
              'Specifies the project content directory. The default value is the directory where the command is executed.',
            default: '.',
          },
          'lint-config': {
            description: 'Severity level for config file linting.',
            choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
            default: 'warn' as RuleSeverity,
          },
        }),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'translate';
      commandWrapper(handleTranslations)(argv);
    }
  )
  .command(
    'eject <type> [path]',
    'Helper function to eject project elements for customization.',
    (yargs) =>
      yargs
        .positional('type', {
          description:
            'Specifies what type of project element to eject. Currently this value must be `component`.',
          demandOption: true,
          choices: ['component'],
        })
        .positional('path', {
          description: 'Filepath to a component or filepath with glob pattern.',
          type: 'string',
        })
        .options({
          'project-dir': {
            alias: 'd',
            type: 'string',
            description:
              'Specifies the project content directory. The default value is the directory where the command is executed.',
            default: '.',
          },
          force: {
            alias: 'f',
            type: 'boolean',
            description:
              'Skips the "overwrite existing" confirmation when ejecting a component that is already ejected in the destination.',
          },
          'lint-config': {
            description: 'Severity level for config file linting.',
            choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
            default: 'warn' as RuleSeverity,
          },
        }),
    (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'eject';
      commandWrapper(handleEject)(argv as Arguments<EjectOptions>);
    }
  )
  .command(
    'respect [files...]',
    'Run Arazzo tests.',
    (yargs) => {
      return yargs
        .positional('files', {
          describe: 'Test files or glob pattern.',
          type: 'string',
          array: true,
          default: [],
        })
        .env('REDOCLY_CLI_RESPECT')
        .options({
          input: {
            alias: 'i',
            describe: 'Input parameters.',
            type: 'string',
          },
          server: {
            alias: 'S',
            describe: 'Server parameters.',
            type: 'string',
          },
          workflow: {
            alias: 'w',
            describe: 'Workflow name.',
            type: 'string',
            array: true,
          },
          skip: {
            alias: 's',
            describe: 'Workflow to skip.',
            type: 'string',
            array: true,
          },
          verbose: {
            alias: 'v',
            describe: 'Apply verbose mode.',
            type: 'boolean',
          },
          'har-output': {
            describe: 'Har file output name.',
            type: 'string',
          },
          'json-output': {
            describe: 'JSON file output name.',
            type: 'string',
          },
          'client-cert': {
            describe: 'Mutual TLS client certificate.',
            type: 'string',
          },
          'client-key': {
            describe: 'Mutual TLS client key.',
            type: 'string',
          },
          'ca-cert': {
            describe: 'Mutual TLS CA certificate.',
            type: 'string',
          },
          severity: {
            describe: 'Severity of the check.',
            type: 'string',
          },
        });
    },
    async (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'respect';
      const { handleRun } = await import('@redocly/respect-core');
      commandWrapper(handleRun)(argv as Arguments<RespectOptions>);
    }
  )
  .command(
    'generate-arazzo <descriptionPath>',
    'Auto-generate arazzo description file from an API description.',
    (yargs) => {
      return yargs
        .positional('descriptionPath', {
          describe: 'Description file path.',
          type: 'string',
        })
        .env('REDOCLY_CLI_RESPECT')
        .options({
          'output-file': {
            alias: 'o',
            describe: 'Output File name.',
            type: 'string',
            requiresArg: true,
          },
        });
    },
    async (argv) => {
      process.env.REDOCLY_CLI_COMMAND = 'generate-arazzo';
      const { handleGenerate } = await import('@redocly/respect-core');
      commandWrapper(handleGenerate)(argv as Arguments<GenerateArazzoFileOptions>);
    }
  )
  .completion('completion', 'Generate autocomplete script for `redocly` command.')
  .demandCommand(1)
  .middleware([notifyUpdateCliVersion])
  .strict().argv;
