YAPI API 代码生成器 CLI 工具

130 阅读4分钟

使用 Node.js 开发 YAPI API 代码生成器 CLI 工具

在软件开发过程中,API 是系统之间沟通的桥梁,尤其是当项目中存在多个接口时,手动编写接口调用代码变得既繁琐又容易出错。为了提高开发效率并保持代码一致性,自动化生成 API 请求代码成为了一种有效的解决方案。本文将介绍如何使用 Node.js 开发一个 YAPI API 代码生成器 CLI 工具,帮助开发者自动化生成 API 请求代码,简化接口调用的开发流程。

github:github.com/yangboxun/y…

背景与需求

为什么需要 API 代码生成工具?

  1. 接口繁多且频繁变动:随着接口数量的增加,手动编写每个接口的请求代码既耗时又容易出错。而接口文档通常会随着开发进度发生变动,因此及时更新代码是一项挑战。
  2. 代码一致性:手动编写 API 请求代码时,代码风格和请求参数的处理可能会有所不同,导致代码不统一。自动化工具能够帮助保持代码的一致性。
  3. 提高开发效率:API 代码生成器能够基于接口文档自动生成请求代码,节省大量的开发时间,并减少重复劳动。

工具的构建

我们将使用 Node.js 创建一个 CLI 工具,这个工具可以从 YAPI 获取接口数据,并生成对应的 API 请求代码。我们将以下技术栈进行组合:

  • Commander:用于构建 CLI 工具的命令行解析器。
  • Inquirer:用于交互式的命令行提问,帮助用户输入配置项。
  • Chalk:用于在命令行中输出彩色文本,提高可读性。
  • Axios:用于向 YAPI 发送请求获取接口数据。
  • FS 和 Path:用于文件操作和路径处理。
  • EJS:用于生成 API 请求代码的模板引擎。
  • YAPI Generator:用于处理从 YAPI 获取到的数据并生成代码。

1. 创建 CLI 工具框架

使用 Commander 创建一个命令行工具框架,在工具中,我们支持以下功能:

  • 配置文件支持:允许用户通过配置文件指定 YAPI 地址、Token、输出文件路径等参数。
  • 交互式配置:如果用户没有提供配置文件,则通过 Inquirer 提供交互式输入。
  • API 代码生成:从 YAPI 获取接口列表,并基于接口定义生成 JavaScript 或 TypeScript 的 API 请求代码。

2. 完整代码分析

以下是完整的 CLI 工具代码实现,它的功能包括读取配置、生成 API 请求代码、处理输出文件等:

#!/usr/bin/env node
import { Command } from 'commander';
import inquirer from 'inquirer';
import chalk from 'chalk';
import YapiGenerator from './generator';
import fs from 'fs';
import path from 'path';

const program = new Command();

program
  .version('1.0.0')
  .description('YAPI API 生成器 CLI')
  .option('-c, --config <path>', '配置文件路径')
  .action(async (options)=>{
    const configPath = options.config || './yapi-api-generator-config.json';
    let config = null;
    // 检查配置文件是否存在
    if (fs.existsSync(configPath)) {
      console.log(chalk.green(`使用该路径下的配置文件 ${configPath}`));
      config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
    } else {
      // 如果配置文件不存在,交互式生成配置文件
      console.log(chalk.yellow(`没有找到该路径下的配置文件 ${configPath}.`));
      config = await inquirer.prompt([
        {
          type: 'input',
          name: 'baseUrl',
          message: '输入Yapi地址:',
        },
        {
          type: 'input',
          name: 'token',
          message: '输入项目token:',
        },
        {
          type: 'input',
          name: 'output',
          message: '输入输出文件路径:',
        },
        {
          type: 'list',
          name: 'targetLanguage',
          message: '输入语言:',
          choices: ['javascript', 'typescript']
        },
        
      ]);
      fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
      console.log(chalk.green(`文件已被创建 ${configPath}`));
    }

    // 参数验证
    if (!config.token || !config.baseUrl) {
      console.error(chalk.red('缺少必要参数:token, baseUrl'));
      process.exit(1);
    }

    // 创建输出目录
    const outputDir = path.dirname(config.output);
    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir, { recursive: true });
    }

    try {
      const generator = new YapiGenerator({
        baseUrl: config.baseUrl,
        token: config.token,
        targetLanguage: config.targetLanguage,
        apiTemplate: config.apiTemplate
      });

      console.log(chalk.blue('开始生成API代码...'));
      const result = await generator.generateCode();
      
      if (!result || result.length === 0) {
        console.error(chalk.red('未生成任何API代码'));
        return;
      }

      // 合并所有API代码
      let apiCode = '';
      let typeCode = '';

      for (const category of result) {
        if (category._apiCodes) {
          apiCode += category._apiCodes.codes + '\n\n';
          if (config.targetLanguage === 'javascript') {
            typeCode += category._apiCodes.tsTypes + '\n\n';
          }
        }
      }

      // 写入API代码
      fs.writeFileSync(config.output, apiCode);
      if (config.targetLanguage === 'typescript') {
        const typeFilePath = path.join(outputDir, 'types.ts');
        fs.writeFileSync(typeFilePath, typeCode);
      }

      console.log(chalk.green(`API代码生成成功!`));
      console.log(chalk.green(`主文件: ${path.resolve(config.output)}`));
      if (config.targetLanguage === 'typescript') {
        console.log(chalk.green(`类型文件: ${path.resolve(outputDir, 'types.ts')}`));
      }
    } catch (error) {
      console.error(chalk.red('生成API代码时出错:'), error);
      process.exit(1);
    }
  })

program.parse(process.argv);

3. 代码解析

  1. 配置文件支持:通过 program.option 允许用户指定配置文件路径。如果没有指定,则默认使用 yapi-api-generator-config.json
  2. 交互式配置:如果配置文件不存在,工具将使用 Inquirer 提供交互式界面,要求用户输入 YAPI 地址、Token、输出文件路径等信息。
  3. API 代码生成:通过 YapiGenerator 类获取 YAPI 接口数据并生成相应的 API 请求代码,支持生成 JavaScript 或 TypeScript 格式的代码。
  4. 输出文件处理:工具会自动创建输出目录,并将生成的代码写入指定的文件中。

总结

通过本文,我们介绍了如何使用 Node.js 开发一个 YAPI API 代码生成器 CLI 工具。这个工具能够自动化生成 API 请求代码,极大地提高了开发效率和代码一致性。通过结合 CommanderInquirerEJS,我们不仅简化了配置和代码生成过程,还为开发者提供了一个灵活且高效的开发工具。希望你能在自己的项目中使用这个工具,提升开发效率!