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.10

Published

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

Readme

ruoyi-eggjs-cli

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

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

特性

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

安装

全局安装(推荐)

$ npm install -g ruoyi-eggjs-cli

本地安装

$ 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

FRP 内网穿透(内置版本 v0.45.0)

使用 FRP 功能可以将本地服务暴露到公网,方便开发和测试:

# 完整示例(所有参数必填)
$ rec frp 127.0.0.1:7001 -saddr frp.example.com -sport 39998 -auth your_token

# 指定本地端口(IP 默认为 127.0.0.1)
$ rec frp 7001 -saddr frp.example.com -sport 39998 -auth your_token

参数说明:

| 参数 | 说明 | 是否必填 | | --- | --- | --- | | localURL | 本地服务地址,格式:IP:PORTPORT | 必填 | | -saddr, --serverAddr | FRP 服务端地址 | 必填 | | -sport, --serverPort | FRP 服务端端口 | 必填 | | -auth, --authToken | 身份验证令牌 | 必填 | | -cdomain, --customDomains | 自定义域名 | 可选 |

使用场景:

  • 本地开发时,需要让远程客户端访问本地服务
  • 微信小程序开发,需要 HTTPS 域名进行调试
  • 临时分享本地服务给团队成员测试
  • 内网穿透,访问内网服务

工作原理

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');
}

SQLite 示例

# 输入
./mapper/
  └── sqlite/
      └── local/
          └── CacheMapper.xml

# 输出
./app/service/db/
  └── sqlite/
      └── local/
          └── CacheMapper.js

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

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 等:

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

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

开发工作流

推荐流程

  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(自定义插件)
  • MongoDB(自定义插件)

完整示例项目

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

相关链接


关于 ruoyi-eggjs 项目

本工具是 ruoyi-eggjs 项目的核心开发工具。

ruoyi-eggjs 是一个基于 Egg.js 的企业级后台管理系统,参照若依(RuoYi)架构设计,提供完善的权限管理、用户管理、系统监控等功能,是快速开发企业级应用的最佳选择。

主要特性

  • 🎯 完整的权限系统:基于 RBAC 的权限控制,支持细粒度权限管理
  • 🚀 开箱即用:集成常用功能模块,快速启动项目开发
  • 🔧 MyBatis 风格:采用 XML 风格的 SQL 编写,熟悉的开发体验
  • 📦 模块化设计:松耦合的插件体系,按需使用
  • 🛡️ 企业级安全:XSS 防护、SQL 注入防护、访问控制等
  • 📊 系统监控:在线用户、登录日志、操作日志、定时任务等

项目地址

相关插件

联系方式

贡献指南

欢迎提交 Issue 和 Pull Request!

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


License

MIT