APIJSON 是一种专为 API 而设计的 JSON 传输结构协议,它可以让前端开发者像写 SQL 一样灵活地请求和操作数据库,而无需后端编写任何接口代码。
本项目是 APIJSON 的 NestJS + TypeScript 实现,支持 MySQL 数据库,提供了完整的 CRUD 操作、JOIN 查询、子查询、聚合函数、事务管理等高级功能。
- ✅ 完整的 CRUD 操作:支持 GET、GETS、HEAD、HEADS、POST、PUT、DELETE、CRUD 等请求方法
- ✅ 灵活的查询条件:支持各种 WHERE 操作符(=、!=、>、<、>=、<=、IN、NOT IN、BETWEEN、LIKE 等)
- ✅ JOIN 查询:支持多种 JOIN 类型(APP、INNER、LEFT、RIGHT、FULL、OUTER 等)
- ✅ 高级特性:
- 子查询
- 聚合函数(COUNT、SUM、AVG、MIN、MAX)
- 分组查询(GROUP BY)
- 事务管理
- ✅ 权限管理:
- 基于 Redis 的用户认证
- 表级权限控制
- 列级权限控制
- 角色权限管理
- ✅ 安全性:
- 参数化查询防止 SQL 注入
- 请求验证
- 速率限制
- ✅ 日志记录:集成 Winston 日志系统
- ✅ 错误处理:统一的错误处理和响应格式
- ✅ 性能优化:连接池管理、查询缓存
- ✅ 完整的测试:单元测试和 E2E 测试
nestjs-apijson/
├── src/
│ ├── common/ # 公共模块
│ │ ├── decorators/ # 装饰器
│ │ ├── filters/ # 异常过滤器
│ │ ├── guards/ # 守卫
│ │ ├── interceptors/ # 拦截器
│ │ └── pipes/ # 管道
│ ├── config/ # 配置模块
│ ├── controllers/ # 控制器
│ ├── interfaces/ # 接口定义
│ ├── modules/ # 功能模块
│ │ ├── advanced/ # 高级特性模块
│ │ ├── builder/ # SQL 构建器模块
│ │ ├── cache/ # 缓存模块
│ │ ├── database/ # 数据库模块
│ │ ├── executor/ # SQL 执行器模块
│ │ ├── parser/ # 解析器模块
│ │ ├── permission/ # 权限管理模块
│ │ └── verifier/ # 验证器模块
│ ├── types/ # 类型定义
│ ├── app.module.ts # 应用主模块
│ └── main.ts # 应用入口
├── test/ # 测试文件
│ ├── e2e/ # E2E 测试
│ ├── setup.ts # 测试设置
│ └── utils/ # 测试工具
├── .env.example # 环境变量示例
├── package.json
├── tsconfig.json
├── nest-cli.json
└── README.md
npm install复制 .env.example 文件为 .env,并根据你的环境修改配置:
cp .env.example .env主要配置项:
# 应用配置
NODE_ENV=development
PORT=3000
# 数据库配置
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=password
DB_DATABASE=apijson
# Redis 配置
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
# JWT 配置
JWT_SECRET=your-secret-key
JWT_EXPIRES_IN=7d# 开发模式
npm run start:dev
# 生产模式
npm run build
npm run start:prod# 单元测试
npm run test
# E2E 测试
npm run test:e2e
# 测试覆盖率
npm run test:covPOST /apijson/get
Content-Type: application/json
{
"User": {
"id": 1
}
}响应:
{
"code": 200,
"message": "success",
"data": {
"User": {
"id": 1,
"name": "张三",
"age": 25
}
}
}POST /apijson/gets
Content-Type: application/json
{
"User[]": {
"id": {">=": 1},
"@order": "id-",
"@limit": 10
}
}POST /apijson/head
Content-Type: application/json
{
"User": {
"id": {">=": 1}
}
}响应:
{
"code": 200,
"message": "success",
"data": {
"User": 100
}
}POST /apijson/post
Content-Type: application/json
{
"User": {
"name": "李四",
"age": 30
}
}POST /apijson/put
Content-Type: application/json
{
"User": {
"id": 1,
"name": "王五"
}
}POST /apijson/delete
Content-Type: application/json
{
"User": {
"id": 1
}
}POST /apijson/crud
Content-Type: application/json
{
"User": {
"id": 1,
"name": "更新用户"
},
"Comment[]": {
"userId": 1
},
"Moment": {
"id": 1,
"@delete": true
}
}| 操作符 | 说明 | 示例 |
|---|---|---|
= |
等于 | {"id": 1} |
!= |
不等于 | {"id!": 1} |
> |
大于 | {"age>": 20} |
< |
小于 | {"age<": 30} |
>= |
大于等于 | {"age>=": 20} |
<= |
小于等于 | {"age<=": 30} |
{} |
IN | {"id{}": [1, 2, 3]} |
!{} |
NOT IN | {"id!{}": [1, 2, 3]} |
>< |
BETWEEN | {"age><": [20, 30]} |
!>< |
NOT BETWEEN | {"age!><": [20, 30]} |
~ |
LIKE | {"name~": "张"} |
!~ |
NOT LIKE | {"name!~": "张"} |
POST /apijson/get
Content-Type: application/json
{
"User": {
"id": 1,
"Comment@": {
"userId": 1
}
}
}JOIN 类型:
@- APP JOIN(LEFT JOIN)&- INNER JOIN|- FULL JOIN<- LEFT JOIN>- RIGHT JOIN!- OUTER JOIN^- SIDE JOIN()- ANTI JOIN()- FOREIGN JOIN~- ASOF JOIN
{
"User[]": {
"@order": "id+,name-"
}
}+ 表示升序,- 表示降序。
{
"User[]": {
"@limit": 10,
"@offset": 20
}
}{
"User": {
"id": 1,
"@column": "id,name,age"
}
}{
"User[]": {
"@group": "department",
"COUNT(id)": "count"
}
}POST /advanced/subquery
Content-Type: application/json
{
"subqueries": [
{
"alias": "user_count",
"tableName": "User",
"where": {"id": {">=": 1}}
}
]
}POST /advanced/aggregate
Content-Type: application/json
{
"tableName": "User",
"aggregateFunction": "COUNT",
"column": "id",
"where": {"age": {">": 20}}
}支持的聚合函数:COUNT、SUM、AVG、MIN、MAX
POST /advanced/group-aggregate
Content-Type: application/json
{
"tableName": "User",
"groupBy": ["department"],
"aggregateFunctions": {
"COUNT(id)": "COUNT(`id`)",
"AVG(age)": "AVG(`age`)"
}
}POST /advanced/transaction
Content-Type: application/json
{
"queries": [
{
"tableName": "User",
"operation": "INSERT",
"data": {"name": "用户1", "age": 25}
},
{
"tableName": "User",
"operation": "INSERT",
"data": {"name": "用户2", "age": 30}
}
]
}GET /permission/tablesPOST /permission/tables/User
Content-Type: application/json
{
"roles": ["ADMIN"],
"canSelect": true,
"canInsert": true,
"canUpdate": true,
"canDelete": true
}POST /permission/check
Content-Type: application/json
{
"userId": "user123",
"tableName": "User",
"operation": "SELECT"
}POST /permission/check-batch
Content-Type: application/json
{
"userId": "user123",
"tableOperations": [
{"tableName": "User", "operation": "SELECT"},
{"tableName": "Comment", "operation": "INSERT"}
]
}| 端点 | 方法 | 说明 |
|---|---|---|
/apijson/get |
POST | 单表查询 |
/apijson/gets |
POST | 多表查询 |
/apijson/head |
POST | 计数查询 |
/apijson/heads |
POST | 多表计数 |
/apijson/post |
POST | 创建数据 |
/apijson/put |
POST | 更新数据 |
/apijson/delete |
POST | 删除数据 |
/apijson/crud |
POST | 混合操作 |
| 端点 | 方法 | 说明 |
|---|---|---|
/advanced/subquery |
POST | 执行子查询 |
/advanced/aggregate |
POST | 执行聚合函数 |
/advanced/group-aggregate |
POST | 执行分组聚合 |
/advanced/transaction |
POST | 执行事务 |
| 端点 | 方法 | 说明 |
|---|---|---|
/permission/tables |
GET | 获取所有表权限 |
/permission/tables/:tableName |
POST | 设置表权限 |
/permission/check |
POST | 检查用户权限 |
/permission/check-batch |
POST | 批量检查权限 |
/permission/users/:userId |
GET | 获取用户权限 |
/permission/users/:userId |
POST | 设置用户权限 |
| 端点 | 方法 | 说明 |
|---|---|---|
/health |
GET | 健康检查 |
所有 API 响应都遵循统一的格式:
{
"code": 200,
"message": "success",
"data": {
// 响应数据
}
}{
"code": 400,
"message": "请求参数错误",
"errors": [
{
"field": "User.id",
"message": "id 不能为空"
}
]
}| 状态码 | 说明 |
|---|---|
| 200 | 成功 |
| 201 | 创建成功 |
| 400 | 请求参数错误 |
| 401 | 未授权 |
| 403 | 禁止访问 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
NODE_ENV- 运行环境(development/production)PORT- 服务端口API_PREFIX- API 路径前缀GLOBAL_PREFIX- 全局路由前缀
DB_HOST- 数据库主机DB_PORT- 数据库端口DB_USERNAME- 数据库用户名DB_PASSWORD- 数据库密码DB_DATABASE- 数据库名称DB_SYNCHRONIZE- 是否同步数据库结构DB_LOGGING- 是否记录 SQL 日志
REDIS_HOST- Redis 主机REDIS_PORT- Redis 端口REDIS_PASSWORD- Redis 密码REDIS_DB- Redis 数据库编号
JWT_SECRET- JWT 密钥JWT_EXPIRES_IN- JWT 过期时间
LOG_LEVEL- 日志级别LOG_FILE- 日志文件路径
- 在
src/modules/下创建新模块目录 - 创建模块文件、服务文件、控制器文件
- 在
app.module.ts中导入新模块
在 src/common/decorators/ 下创建装饰器文件:
import { SetMetadata } from '@nestjs/common';
export const MY_DECORATOR_KEY = 'myDecorator';
export const MyDecorator = (data?: any) => SetMetadata(MY_DECORATOR_KEY, data);在 src/common/guards/ 下创建守卫文件:
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
@Injectable()
export class MyGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
// 守卫逻辑
return true;
}
}在 src/common/interceptors/ 下创建拦截器文件:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class MyInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// 拦截器逻辑
return next.handle();
}
}单元测试位于各个模块的 .spec.ts 文件中。
运行单元测试:
npm run testE2E 测试位于 test/e2e/ 目录中。
运行 E2E 测试:
npm run test:e2e生成测试覆盖率报告:
npm run test:cov- 连接池管理:使用数据库连接池提高性能
- 查询缓存:使用 Redis 缓存查询结果
- 索引优化:为常用查询字段添加索引
- 批量操作:使用批量插入、更新、删除减少数据库操作
- 分页查询:避免一次性查询大量数据
- 使用 HTTPS:在生产环境中使用 HTTPS
- 强密码策略:设置强密码并定期更换
- SQL 注入防护:使用参数化查询
- XSS 防护:对用户输入进行过滤和转义
- CSRF 防护:使用 CSRF Token
- 速率限制:防止暴力攻击
- 日志监控:监控异常日志及时发现安全问题
使用分页查询:
{
"User[]": {
"@limit": 100,
"@offset": 0
}
}- 添加适当的索引
- 使用分页查询
- 避免使用
SELECT * - 使用查询缓存
使用事务端点:
POST /advanced/transaction使用权限管理端点配置表权限和用户权限。
欢迎贡献代码!请遵循以下步骤:
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 创建 Pull Request
本项目采用 MIT 许可证。
如有问题或建议,请提交 Issue 或 Pull Request。
感谢 APIJSON 原作者的开源贡献。
- 初始版本发布
- 实现完整的 CRUD 操作
- 支持 JOIN 查询
- 实现高级特性(子查询、聚合函数、事务)
- 实现权限管理
- 完善的测试覆盖