export async function renderUserInputType()

in packages/@aws-cdk/user-input-gen/lib/user-input-gen.ts [7:136]


export async function renderUserInputType(config: CliConfig): Promise<string> {
  const scope = new Module('aws-cdk');

  scope.documentation.push( '-------------------------------------------------------------------------------------------');
  scope.documentation.push(`GENERATED FROM ${SOURCE_OF_TRUTH}.`);
  scope.documentation.push('Do not edit by hand; all changes will be overwritten at build time from the config file.');
  scope.documentation.push('-------------------------------------------------------------------------------------------');

  const userInputType = new StructType(scope, {
    export: true,
    name: 'UserInput',
    docs: {
      summary: 'The structure of the user input -- either CLI options or cdk.json -- generated from packages/aws-cdk/lib/config.ts',
    },
  });

  // add required command
  scope.addImport(new SelectiveModuleImport(scope, './user-configuration', ['Command']));
  const commandEnum = Type.fromName(scope, 'Command');

  userInputType.addProperty({
    name: 'command',
    type: commandEnum,
    docs: {
      summary: 'The CLI command name',
    },
    optional: true,
  });

  // add global options
  const globalOptionType = new StructType(scope, {
    export: true,
    name: 'GlobalOptions',
    docs: {
      summary: 'Global options available to all CLI commands',
    },
  });
  for (const [optionName, option] of Object.entries(config.globalOptions)) {
    globalOptionType.addProperty({
      name: kebabToCamelCase(optionName),
      type: convertType(option.type, option.count),
      docs: {
        default: normalizeDefault(option.default),
        summary: option.desc,
        deprecated: option.deprecated ? String(option.deprecated) : undefined,
      },
      optional: true,
    });
  }

  userInputType.addProperty({
    name: 'globalOptions',
    type: Type.fromName(scope, globalOptionType.name),
    docs: {
      summary: 'Global options available to all CLI commands',
    },
    optional: true,
  });

  // add command-specific options
  for (const [commandName, command] of Object.entries(config.commands)) {
    let commandType: Type = Type.anonymousInterface([]);
    const commandOptions = Object.entries(command.options ?? {});

    // if we have something to add to an interface
    if (command.arg || commandOptions.length) {
      const commandStruct = new StructType(scope, {
        export: true,
        name: `${kebabToPascal(commandName)}Options`,
        docs: {
          summary: command.description,
          remarks: command.aliases ? `aliases: ${command.aliases.join(' ')}` : undefined,
        },
      });
      commandType = Type.fromName(scope, commandStruct.name);

      // add command level options
      for (const [optionName, option] of commandOptions) {
        commandStruct.addProperty({
          name: kebabToCamelCase(optionName),
          type: convertType(option.type, option.count),
          docs: {
          // Notification Arns is a special property where undefined and [] mean different things
            default: optionName === 'notification-arns' ? 'undefined' : normalizeDefault(option.default),
            summary: option.desc,
            deprecated: option.deprecated ? String(option.deprecated) : undefined,
            remarks: option.alias ? `aliases: ${Array.isArray(option.alias) ? option.alias.join(' ') : option.alias}` : undefined,
          },
          optional: true,
        });
      }

      // add positional argument associated with the command
      if (command.arg) {
        commandStruct.addProperty({
          name: command.arg.name,
          type: command.arg.variadic ? Type.arrayOf(Type.STRING) : Type.STRING,
          docs: {
            summary: `Positional argument for ${commandName}`,
          },
          optional: true,
        });
      }
    }

    userInputType.addProperty({
      name: kebabToCamelCase(commandName),
      type: commandType,
      docs: {
        summary: command.description,
        remarks: command.aliases ? `aliases: ${command.aliases.join(' ')}` : undefined,
      },
      optional: true,
    });
  }

  const ts = new TypeScriptRenderer({
    disabledEsLintRules: [
      EsLintRules.MAX_LEN, // the default disabled rules result in 'Definition for rule 'prettier/prettier' was not found
      '@typescript-eslint/consistent-type-imports', // (ironically) typewriter does not support type imports
    ],
  }).render(scope);

  return prettier.format(ts, {
    parser: 'typescript',
    printWidth: 150,
    singleQuote: true,
    quoteProps: 'consistent',
  });
}