npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ruoyi-eggjs-cli

v1.1.11

Published

> Egg.js MyBatis 风格的 Service 代码生成器

Downloads

253

Readme

ruoyi-eggjs-cli

Egg.js MyBatis 风格的 Service 代码生成器

基于 MyBatis XML 映射文件自动生成 Egg.js Service 层代码,减少重复劳动,提高开发效率。

| 公众号 | 微信交流群 | | -------------------------------------------- | --------------------------------------------------------------- | | 公众号 | 微信交流群 |

目录

特性

  • ✅ 自动扫描 XML Mapper 文件并生成对应的 Service 代码
  • ✅ 支持多数据库类型(MySQL、SQLite、PostgreSQL 等)
  • ✅ 支持多数据源配置
  • ✅ 实时监听模式,XML 文件变化时自动重新生成
  • ✅ 自动生成符合命名规范的方法(驼峰命名)
  • ✅ 智能识别 SQL 类型(select、selects、insert、update、delete)
  • ✅ 生成进度可视化显示

安装

$ npm install ruoyi-eggjs-cli --save-dev

使用方法

基础用法

在项目根目录执行:

# 使用当前目录作为项目路径
$ psy mapper

# 指定项目路径
$ psy mapper /path/to/your/project

完整参数

$ psy mapper [projectPath] [options]

参数说明:

| 参数 | 说明 | 默认值 | | ---------------------- | ----------------------------------- | ------------ | | projectPath | 项目路径 | 当前工作目录 | | -m, --mapperDir | Mapper XML 文件所在目录(相对路径) | mapper | | -d, --defaultDatabse | 默认数据库类型 | mysql | | -w, --watch | 是否启用自动监听模式 | true |

使用示例

# 基础用法,使用默认配置
$ psy mapper

# 指定 Mapper 目录
$ psy mapper -m custom-mapper

# 指定默认数据库为 SQLite
$ psy mapper -d sqlite

# 禁用自动监听
$ psy mapper -w false

# 组合使用
$ psy mapper /my/project -m mapper -d mysql -w true

工作原理

1. 扫描 XML 文件

CLI 会扫描指定目录下的所有 .xml 文件:

./mapper/
  ├── mysql/
  │   └── ruoyi/
  │       ├── SysUserMapper.xml
  │       └── SysRoleMapper.xml
  └── sqlite/
      └── cache/
          └── CacheMapper.xml

2. 生成 Service 代码

根据 XML 文件的目录结构和内容,自动生成对应的 Service 文件:

./app/service/db/
  ├── mysql/
  │   └── ruoyi/
  │       ├── SysUserMapper.js
  │       └── SysRoleMapper.js
  └── sqlite/
      └── cache/
          └── CacheMapper.js

3. Service 代码结构

生成的 Service 类包含以下内容:

  • 基础方法

    • mapper(sqlid, values, params) - 获取 SQL 语句
    • db() - 获取数据库实例
  • 自动生成的方法(根据 XML 中的 SQL 语句):

    • xxxMapper(values, params) - 生成 SQL
    • xxx(values, params) - 执行 SQL 并返回结果

示例

输入:XML Mapper 文件

<!-- mapper/mysql/ruoyi/SysUserMapper.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper/mysql/ruoyi/SysUserMapper.xml">

    <select id="selectUserList">
        SELECT * FROM sys_user
        <where>
            <if test="userName">
                AND user_name LIKE '%${userName}%'
            </if>
        </where>
        ORDER BY create_time DESC
        LIMIT ?, ?
    </select>

    <select id="selectUserById">
        SELECT * FROM sys_user WHERE user_id = ?
    </select>

    <insert id="insertUser">
        INSERT INTO sys_user (user_name, nick_name, email)
        VALUES (#{userName}, #{nickName}, #{email})
    </insert>

    <update id="updateUser">
        UPDATE sys_user
        <set>
            <if test="userName">user_name = #{userName},</if>
            <if test="email">email = #{email},</if>
            update_time = NOW()
        </set>
        WHERE user_id = ?
    </update>

    <delete id="deleteUser">
        DELETE FROM sys_user WHERE user_id = ?
    </delete>

</mapper>

输出:生成的 Service 代码

// app/service/db/mysql/ruoyi/SysUserMapper.js
const Service = require("egg").Service;

class SysUserMapperService extends Service {
  mapper(sqlid, values, params) {
    return this.app.mapper(
      "mapper/mysql/ruoyi/SysUserMapper.xml",
      sqlid,
      values,
      params,
    );
  }

  db() {
    return this.app.mysql.get("ruoyi");
  }

  selectUserListMapper(values, params) {
    return this.mapper("selectUserList", values, params);
  }

  async selectUserList(values, params) {
    return await this.db().select(this.selectUserListMapper(values, params));
  }

  selectUserByIdMapper(values, params) {
    return this.mapper("selectUserById", values, params);
  }

  async selectUserById(values, params) {
    return await this.db().select(this.selectUserByIdMapper(values, params));
  }

  insertUserMapper(values, params) {
    return this.mapper("insertUser", values, params);
  }

  async insertUser(values, params) {
    return await this.db().insert(this.insertUserMapper(values, params));
  }

  updateUserMapper(values, params) {
    return this.mapper("updateUser", values, params);
  }

  async updateUser(values, params) {
    return await this.db().update(this.updateUserMapper(values, params));
  }

  deleteUserMapper(values, params) {
    return this.mapper("deleteUser", values, params);
  }

  async deleteUser(values, params) {
    return await this.db().del(this.deleteUserMapper(values, params));
  }
}

module.exports = SysUserMapperService;

使用生成的 Service

// app/controller/user.js
class UserController extends Controller {
  async list() {
    const { ctx } = this;
    const params = ctx.request.body;

    // 调用生成的 Service
    const users = await ctx.service.db.mysql.ruoyi.sysUserMapper.selectUserList(
      ctx.helper.page(params),
      params,
    );

    ctx.body = { code: 200, data: users };
  }

  async info() {
    const { ctx } = this;
    const { userId } = ctx.params;

    const user = await ctx.service.db.mysql.ruoyi.sysUserMapper.selectUserById([
      userId,
    ]);

    ctx.body = { code: 200, data: user };
  }

  async add() {
    const { ctx } = this;
    const user = ctx.request.body;

    const insertId = await ctx.service.db.mysql.ruoyi.sysUserMapper.insertUser(
      [],
      user,
    );

    ctx.body = { code: 200, data: insertId };
  }

  async update() {
    const { ctx } = this;
    const user = ctx.request.body;

    await ctx.service.db.mysql.ruoyi.sysUserMapper.updateUser(
      [user.userId],
      user,
    );

    ctx.body = { code: 200, message: "更新成功" };
  }

  async remove() {
    const { ctx } = this;
    const { userId } = ctx.params;

    await ctx.service.db.mysql.ruoyi.sysUserMapper.deleteUser([userId]);

    ctx.body = { code: 200, message: "删除成功" };
  }
}

自动监听模式

启用监听模式(默认开启)后,CLI 会自动监听 XML 文件的变化:

$ psy mapper
✔ 生成成功
✔ 自动监听模式已启动

监听功能:

  1. 文件变更:修改 XML 文件后自动重新生成对应的 Service
  2. 文件删除:删除 XML 文件后自动删除对应的 Service 文件
  3. 智能更新:只在 SQL ID 发生变化时才重新生成,避免不必要的文件写入
# 修改 XML 文件后
./mapper/mysql/ruoyi/SysUserMapper.xml has been changed

# 删除 XML 文件后
./mapper/mysql/ruoyi/SysRoleMapper.xml has been removed

目录结构对照

单数据库

# 输入
./mapper/
  └── dbname/
      └── TableMapper.xml

# 输出
./app/service/db/
  └── dbname/
      └── TableMapper.js

# Service 中的 db() 方法
db() {
    return this.app.mysql.get('dbname');
}

多数据库

# 输入
./mapper/
  └── mysql/
      └── dbname/
          └── TableMapper.xml

# 输出
./app/service/db/
  └── mysql/
      └── dbname/
          └── TableMapper.js

# Service 中的 db() 方法
db() {
    return this.app.mysql.get('dbname');
}

SQL 类型映射

CLI 会根据 XML 中的标签类型,自动调用对应的数据库方法:

| XML 标签 | 数据库方法 | 返回值 | | ----------- | ------------ | --------------------------------------- | | <select> | .select() | 单条记录或 null,多条记录时返回记录数组 | | <selects> | .selects() | 记录数组 | | <insert> | .insert() | 插入的 ID | | <update> | .update() | 影响的行数 | | <delete> | .del() | 删除的行数 | | <sql> | .run() | 执行结果 |

命名规范

Service 类名

基于 XML 文件名生成,使用大驼峰命名(PascalCase):

  • SysUserMapper.xmlSysUserMapperService
  • sys-role-mapper.xmlSysRoleMapperService
  • sys_menu_mapper.xmlSysMenuMapperService

方法名

基于 SQL ID 生成,使用小驼峰命名(camelCase):

  • selectUserListselectUserList() / selectUserListMapper()
  • select_user_by_idselectUserById() / selectUserByIdMapper()
  • insert-userinsertUser() / insertUserMapper()

配置要求

使用本 CLI 需要项目中已配置以下插件:

1. ruoyi-eggjs-mybatis

用于 MyBatis XML 映射:

// config/plugin.js
exports.mybatis = {
  enable: true,
  package: "ruoyi-eggjs-mybatis",
};

2. 数据库插件

如 ruoyi-eggjs-mysql、ruoyi-eggjs-sqlite、ruoyi-eggjs-pgsql 等:

// config/plugin.js
exports.mysql = {
  enable: true,
  package: "ruoyi-eggjs-mysql",
};

exports.sqlite = {
  enable: true,
  package: "ruoyi-eggjs-sqlite",
};

exports.pgsql = {
  enable: true,
  package: "ruoyi-eggjs-pgsql",
};

开发工作流

推荐流程

  1. 启动监听模式

    $ psy mapper
  2. 编写/修改 XML Mapper

    <!-- 新增或修改 SQL -->
    <select id="selectNewData">...</select>
  3. 自动生成 Service

    • CLI 自动检测变化并重新生成 Service 代码
  4. 在 Controller 中使用

    await ctx.service.db.xxx.selectNewData([params]);

集成到开发命令

// package.json
{
  "scripts": {
    "dev": "npm-run-all -p mapper debug",
    "mapper": "psy mapper",
    "debug": "egg-bin debug"
  }
}

运行 npm run dev 即可同时启动 Mapper 生成器和应用调试。

常见问题

1. 为什么要生成 Service 代码?

  • 减少重复代码:避免每个 Mapper 都手写相同的 Service 方法
  • 保持一致性:所有 Service 遵循统一的命名和调用规范
  • 提高效率:XML 改动后自动同步到 Service 层
  • 便于维护:代码自动生成,降低维护成本

2. 可以自定义生成的代码吗?

目前不支持自定义模板。如需特殊逻辑,建议:

  • 在生成的 Service 基础上扩展
  • 或创建新的 Service 类继承生成的类

3. 监听模式会影响性能吗?

不会。监听模式只在开发环境使用,且只监听 XML 文件变化,不会影响应用性能。

4. 如何禁用监听模式?

$ psy mapper -w false

5. 生成的文件可以手动修改吗?

不建议。因为 XML 变化后会重新生成,手动修改会丢失。如需自定义逻辑,建议创建新的 Service 类。

6. 支持哪些数据库?

理论上支持所有通过插件形式集成到 Egg.js 的数据库,如:

  • MySQL(ruoyi-eggjs-mysql)
  • SQLite(ruoyi-eggjs-sqlite)
  • PostgreSQL(ruoyi-eggjs-pgsql)

完整项目

参考 ruoyi-eggjs 项目查看完整使用示例。

请我喝杯咖啡

如果项目对你有帮助,可以请我喝杯咖啡 ☕️

联系方式

贡献指南

欢迎提交 Issue 和 Pull Request!

如果这个项目对你有帮助,请给我们一个 ⭐️ Star 支持一下!


License

MIT