🚀 基于 Axios 的 DSL(领域特定语言)API 声明库,大幅减少重复代码,提升开发效率
- 🎯 DSL 声明式 API - 使用简洁的字符串声明 API 接口,告别重复模板代码
- 🔧 类型安全 - 完整的 TypeScript 支持,提供智能类型提示
- 🚀 零配置 - 开箱即用,无需复杂配置
- 📦 轻量级 - 基于 Axios,无额外依赖
- 🧪 100% 测试覆盖率 - 完整的单元测试覆盖,确保代码质量和稳定性
- 🔄 拦截器支持 - 完整的请求/响应拦截器配置
- 📁 FormData 自动处理 - 智能识别并转换文件上传请求
- 🎨 智能请求头 - 自动设置 Content-Type,支持自定义覆盖
- 🌐 跨技术栈 - 支持 Vue、React、Angular 等所有 JavaScript/TypeScript 项目
# 使用 npm
npm install @siyuan0215/easier-axios-dsl
# 使用 yarn
yarn add @siyuan0215/easier-axios-dsl
# 使用 pnpm
pnpm add @siyuan0215/easier-axios-dsl
// utils/request.ts
import { init } from "@siyuan0215/easier-axios-dsl";
const { generatorAPIS, requestInstance } = init({
requestInterceptors: [
(config) => {
// 添加认证头
config.headers.Authorization = `Bearer ${getToken()}`;
return config;
},
(error) => Promise.reject(error),
],
responseInterceptors: [
(response) => response,
(error) => {
// 统一错误处理
if (error.response?.status === 401) {
// 处理未授权
}
return Promise.reject(error);
},
],
timeout: 10000,
baseURL: "https://api.example.com",
});
export { generatorAPIS, requestInstance };
// api/index.ts
import { generatorAPIS } from "@/utils/request";
const APIS = {
// 获取用户信息 - GET 请求,查询参数
getUserInfo: "GET /api/users q:userId",
// 创建用户 - POST 请求,请求体数据
createUser: "POST /api/users d:name,email,age",
// 更新用户 - PUT 请求,路径参数 + 请求体
updateUser: "PUT /api/users/{id} path:id d:name,email",
// 删除用户 - DELETE 请求,路径参数
deleteUser: "DELETE /api/users/{id} path:id",
// 文件上传 - POST 请求,FormData
uploadFile: "POST /api/upload d.f:file,description",
// 批量操作 - POST 请求,数组数据
batchUpdate: "POST /api/users/batch [d] q:dryRun",
// 通配符模式 - 传递所有参数
wildcardPost: "POST /api/users d:*",
} as const;
export default generatorAPIS(APIS);
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import APIS from '@/api'
// 响应式数据
const user = ref(null)
const formData = ref({ name: '', email: '', age: 0 })
const uploadProgress = ref(0)
// 获取用户信息
const fetchUserInfo = async () => {
try {
const { data } = await APIS.getUserInfo<{data: UserInfo}>({ userId: '123' })
user.value = data
} catch (error) {
console.error('获取用户信息失败:', error)
}
}
// 保存用户
const saveUser = async () => {
try {
const result = await APIS.createUser({
name: formData.value.name,
email: formData.value.email,
age: formData.value.age
})
console.log('用户创建成功:', result)
} catch (error) {
console.error('创建用户失败:', error)
}
}
// 上传文件
const uploadFile = async (file: File) => {
try {
const result = await APIS.uploadFile(
{ file, description: '用户头像' },
undefined, // otherPayload
{
onUploadProgress: (progressEvent) => {
uploadProgress.value = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
)
}
}
)
console.log('文件上传成功:', result)
} catch (error) {
console.error('文件上传失败:', error)
}
}
</script>
[HTTP方法] [URL] [参数载体类型]:[参数列表]
类型 | 说明 | 示例 | 适用场景 |
---|---|---|---|
q |
查询参数 | q:page,size |
GET 请求的 URL 参数 |
path |
路径参数 | path:userId |
动态路由参数 |
d |
请求体数据 | d:name,email |
POST/PUT 请求的 JSON 数据 |
d.f |
FormData | d.f:file,description |
文件上传 |
[d] |
数组数据 | [d] |
批量操作 |
* |
通配符 | d:* |
传递所有参数 |
const APIS = {
// 简单 GET 请求
getUsers: "GET /api/users q:page,size,sort",
// 带路径参数的 GET 请求
getUserById: "GET /api/users/{id} path:id q:include",
// POST 请求,JSON 数据
createUser: "POST /api/users d:name,email,age",
// PUT 请求,路径参数 + 请求体
updateUser: "PUT /api/users/{id} path:id d:name,email",
// DELETE 请求,路径参数
deleteUser: "DELETE /api/users/{id} path:id",
// 文件上传
uploadFile: "POST /api/upload d.f:file,description",
// 批量操作
batchDelete: "POST /api/users/batch-delete [d] q:confirm",
// 通配符模式
flexiblePost: "POST /api/users d:*",
};
// 运行时配置
const result = await APIS.downloadFile(
{ id: "123" }, // majorPayload - 主要参数
undefined, // otherPayload - 额外参数(可选)
{
responseType: "blob",
timeout: 30000,
headers: {
"Custom-Header": "value",
},
returnResponse: true, // 返回完整的响应对象
} // RequestConfig - Axios 配置选项
);
参数 | 类型 | 必填 | 说明 | 示例 |
---|---|---|---|---|
majorPayload | Record<string, any> | any[] |
✅ | 主要请求参数,根据 DSL 声明自动分配到对应位置 | { userId: '123' } |
otherPayload | Record<string, any> |
❌ | 额外参数,仅在数组数据模式下使用 | { extra: 'data' } |
RequestConfig | AxiosRequestConfig |
❌ | Axios 运行时配置选项 | { timeout: 5000 } |
根据 DSL 声明自动将参数分配到不同位置:
// DSL: "GET /api/users/{id} path:id q:page,size d:name,email"
const result = await APIS.getUser(
{
id: "123", // → 路径参数: /api/users/123
page: 1, // → 查询参数: ?page=1
size: 10, // → 查询参数: ?size=10
name: "John", // → 请求体: { name: "John" }
email: "john@example.com" // → 请求体: { email: "john@example.com" }
}
);
仅在数组数据模式 [d]
下使用,用于传递额外的非数组参数:
// DSL: "POST /api/users/batch [d] q:dryRun"
const result = await APIS.batchCreate(
[user1, user2, user3], // majorPayload - 数组数据
{ dryRun: true }, // otherPayload - 额外查询参数
{ timeout: 10000 } // RequestConfig
);
选项 | 类型 | 说明 | 示例 |
---|---|---|---|
returnResponse |
boolean |
返回完整 Axios 响应对象,而非仅 data | { returnResponse: true } |
responseType |
string |
响应数据类型(blob, json, text 等) | { responseType: "blob" } |
timeout |
number |
请求超时时间(毫秒) | { timeout: 5000 } |
headers |
object |
自定义请求头 | { headers: { "Authorization": "Bearer token" } } |
// 1. 基本使用
const user = await APIS.getUser({ id: "123" });
// 2. 带额外配置
const user = await APIS.getUser(
{ id: "123" },
undefined,
{ timeout: 5000 }
);
// 3. 文件下载
const file = await APIS.downloadFile(
{ id: "123" },
undefined,
{
responseType: "blob",
returnResponse: true
}
);
// 4. 数组数据 + 额外参数
const result = await APIS.batchUpdate(
[{ id: 1, name: "John" }, { id: 2, name: "Jane" }],
{ dryRun: true },
{ timeout: 30000 }
);
// 5. 获取完整响应
const response = await APIS.getUser(
{ id: "123" },
undefined,
{ returnResponse: true }
);
// response 包含: { data, status, statusText, headers, config }
项目包含完整的单元测试套件,测试覆盖率达到 100%:
# 运行测试
npm test
# 运行测试并生成覆盖率报告
npm run coverage
# 监听模式
npm run test:watch
- ✅ 核心功能测试 - 完整的 API 生成和调用流程
- ✅ DSL 解析测试 - 各种 DSL 格式的解析验证
- ✅ 参数处理测试 - 查询参数、路径参数、请求体参数处理
- ✅ 拦截器测试 - 请求和响应拦截器功能
- ✅ FormData 处理测试 - 文件上传和表单数据处理
- ✅ 错误处理测试 - 异常情况和错误处理
- ✅ 边界情况测试 - 空参数、特殊字符、极端情况
- ✅ 异常情况测试 - 无效方法、无效 URL、格式错误等
- 测试文件: 5 个
- 测试用例: 199 个
- 覆盖率: 100% (语句、分支、函数、行)
- 测试框架: Vitest
传统方式(冗余代码):
// 需要为每个接口写重复的模板代码
export const getUserInfo = (userId: string) =>
request("/api/users", {
method: "GET",
params: { userId },
});
export const createUser = (userData: UserData) =>
request("/api/users", {
method: "POST",
data: userData,
});
export const updateUser = (id: string, userData: UserData) =>
request(`/api/users/${id}`, {
method: "PUT",
data: userData,
});
DSL 方式(简洁声明):
// 一行声明一个接口,自动生成对应函数
const APIS = {
getUserInfo: "GET /api/users q:userId",
createUser: "POST /api/users d:*",
updateUser: "PUT /api/users/{id} path:id d:*",
};
优势:
- 🎯 代码量减少 70%+ - 大幅减少重复模板代码
- 🚀 开发效率提升 - 快速声明 API 接口
- 🔧 维护成本降低 - 统一的接口管理方式
- 🎨 类型安全 - 完整的 TypeScript 支持
- 🧪 100% 测试覆盖 - 确保代码质量和稳定性
- 🧪 测试优化: 测试覆盖率提升至 100%
- 🐛 Bug 修复: 修复了多个边界情况的处理
- 📚 文档更新: 完善了 API 文档和示例
- ✨ 新增功能: 支持通配符模式
d:*
- 🔧 性能优化: 优化了参数处理逻辑
- 📚 文档完善: 添加了更多使用示例
- ✨ 新增功能: 支持 FormData 自动处理
- 🔧 类型优化: 改进了 TypeScript 类型定义
- 🧪 测试增强: 增加了更多测试用例
- 🎉 首次发布: 基础 DSL 功能
- ✨ 核心功能: API 声明、参数处理、拦截器支持
我们欢迎所有形式的贡献!
# 克隆仓库
git clone https://github.com/siyuan0215/easier-axios-dsl.git
# 安装依赖
npm install
# 运行测试
npm test
# 运行开发服务器
npm run dev
我们使用 Conventional Commits 规范:
feat:
新功能fix:
修复 bugdocs:
文档更新style:
代码格式调整refactor:
代码重构test:
测试相关chore:
构建过程或辅助工具的变动
- 所有新功能必须包含相应的测试用例
- 测试覆盖率必须保持在 100%
- 提交前请运行
npm test
确保所有测试通过
本项目基于 MIT 许可证 开源。
- 📧 Email: [your-email@example.com]
- 🐛 Issues: GitHub Issues
- 📖 文档: 项目 Wiki
⭐ 如果这个项目对你有帮助,请给我们一个 Star!