开发指南
本文档介绍如何使用 TypeSpec 开发和扩展 NexusBook API。
技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| TypeSpec | 1.6.0 | API 定义语言 |
| OpenAPI | 3.0 | API 规范标准 |
| Redocly | 2.12.0 | API 文档生成 |
前置要求
- Node.js 16+
- Make
快速开始
安装依赖
# 安装 npm 依赖
make deps
# 或者手动安装
npm install
生成文档
# 生成 OpenAPI 规范
make openapi
# 构建 API 文档
make build-docs
# 构建完整文档站点
make docs
# 预览文档(浏览器访问 http://localhost:8091)
make serve
输出文件
| 文件 | 说明 |
|---|---|
dist/openapi/@typespec/openapi3/*.yaml |
OpenAPI 规范文件 |
docs/api/index.html |
Redoc 单页 API 文档 |
docs/ |
完整文档站点(生成) |
docs-src/ |
文档源文件(Markdown) |
dist/openapi/openapi.yaml |
合并后的 OpenAPI 入口文件 |
项目命令
# 开发相关
make deps # 安装依赖
make openapi # 生成 OpenAPI 规范
make build-docs # 构建 Redoc 文档
make serve-docs # 预览 Redoc 文档(端口 8091)
# 文档站点
make docs # 构建完整文档站点
make serve # 启动文档服务器(端口 8091)
make clean-docs # 清理生成的文档
# 清理
make clean # 清理生成的文件
添加新模块
1. 创建模块目录
mkdir -p api/extensions/webhooks
2. 创建 TypeSpec 文件
// api/extensions/webhooks/models.tsp
import "@typespec/http";
import "../../shared/index.tsp";
namespace NexusBook.Extensions.Webhooks {
model Webhook {
id: string;
url: string;
events: string[];
}
@route("/webhooks")
interface WebhooksApi {
@get list(): ApiResponse<Webhook[]>;
@post create(@body webhook: Webhook): ApiResponse<Webhook>;
}
}
3. 创建模块入口
// api/extensions/webhooks/index.tsp
import "./models.tsp";
4. 在主入口引入
// api/main.tsp
import "./extensions/webhooks/index.tsp";
5. 重新生成
make openapi
make docs
修改现有模块
- 编辑对应的 .tsp 文件
- 运行
make openapi重新生成 OpenAPI - 运行
make docs重新生成文档站点 - 运行
make serve预览变更
编辑文档
文档结构
docs-src/ # 文档源文件(提交到 Git)
├── guides/ # 开发指南
├── references/ # 参考文档
├── styles/ # 样式文件
├── README.md # 文档说明
└── CONTRIBUTING.md # 贡献指南
docs/ # 生成的文档(不提交到 Git)
├── guides/ # 生成的指南 HTML
├── references/ # 生成的参考 HTML
├── styles/ # 复制的样式
├── api/ # Redoc API 文档
└── index.html # 文档主页
添加新文档
- 在
docs-src/guides/或docs-src/references/创建 Markdown 文件 - 编辑
scripts/build-docs.js,添加文件到对应数组 - 运行
make docs生成 HTML
示例:
// scripts/build-docs.js
const guides = [
// ... 现有文档
{ file: 'my-new-guide', title: '新指南标题' }
];
文档注释规范
使用中英文双语注释
/**
* 获取文档元数据
*
* Get document metadata
*
* 返回字段定义与显示配置,供渲染与校验使用。
* Returns field definitions and display settings for rendering and validation.
*/
@get
@summary("获取文档元数据")
getMetadata(...): ApiResponse<Metadata>;
添加示例
/**
* 创建数据行
*
* Create data row
*
* 示例(cURL):
* ```bash
* curl -X POST 'https://open.nexusbook.app/api/v1/doc/product/123/data?apply=true' \
* -H 'Authorization: Bearer TOKEN' \
* -H 'Content-Type: application/json' \
* -d '{"id":"row-1","values":[{"fieldId":"name","value":{"text":"新产品"}}]}'
* ```
*/
测试 API
使用 curl
# 设置环境变量
export API_BASE="https://open.nexusbook.app/api/v1"
export TOKEN="your_access_token"
# 测试端点
curl -H "Authorization: Bearer $TOKEN" \
"$API_BASE/doc/product/123/metadata"
使用 Postman
- 导入生成的 OpenAPI 文件
- 配置环境变量(base_url, token)
- 测试各个端点
调试技巧
查看生成的 OpenAPI
# 查看 API 规范
cat dist/openapi/@typespec/openapi3/openapi.NexusBook.Api.yaml
# 使用 yq 格式化查看
yq eval dist/openapi/@typespec/openapi3/openapi.NexusBook.Api.yaml
验证 TypeSpec 语法
npx tsp compile api/main.tsp --no-emit
查看编译错误
TypeSpec 编译器会提供详细的错误信息,包括:
- 文件位置
- 错误类型
- 修复建议
常见问题
Q: 如何添加新的错误码?
在 api/shared/common.tsp 中的 ErrorCode 枚举添加:
enum ErrorCode {
// ... 现有错误码
NEW_ERROR_CODE, // 新错误码
}
Q: 如何添加新的字段类型?
- 在
api/shared/constants.tsp的FieldType枚举添加 - 在
api/shared/common.tsp的Valueunion 添加对应类型 - 重新生成 OpenAPI
Q: 如何修改响应格式?
修改 api/shared/common.tsp 中的 ApiResponse 模型,但建议保持向后兼容。
Q: 如何使用生成的 OpenAPI 规范?
生成的 OpenAPI 文件 (dist/openapi/openapi.yaml) 可以:
用于任意后端语言的代码生成
- Python:
openapi-generator - Java/Kotlin:
openapi-generator - TypeScript/JavaScript:
openapi-typescript-codegen - 其他语言:查看 OpenAPI Generator
- Python:
导入到 API 测试工具
- Postman
- Insomnia
- Swagger UI
生成客户端 SDK
例如使用 Python:
openapi-generator-cli generate -i dist/openapi/openapi.yaml -g python -o client-python
Q: 如何调试 TypeSpec 编译错误?
- 检查导入路径是否正确
- 确认所有引用的类型都已定义
- 使用
--trace选项查看详细信息:npx tsp compile api/main.tsp --trace
Q: 如何优化 OpenAPI 文档生成?
- 添加详细的
@summary和@doc注释 - 使用
@example提供示例 - 为模型字段添加描述
- 使用
@deprecated标记废弃的 API
Q: 文档站点样式丢失怎么办?
确保 docs-src/styles/main.css 存在,然后运行:
make docs
TypeSpec 最佳实践
1. 模块组织
- 按功能划分模块(core, content, workflow)
- 每个模块有独立的
index.tsp入口 - 相关的模型和接口放在一起
2. 命名规范
- Model 名称: PascalCase(如
DataRow,Metadata) - Interface 名称: PascalCase + Api 后缀(如
DataApi,ViewsApi) - 字段名称: camelCase(如
fieldId,createdAt) - 枚举值: UPPER_SNAKE_CASE(如
DOC_NOT_FOUND)
3. 类型复用
// 定义可复用的类型
model PageRequest {
page?: int32 = 1;
pageSize?: int32 = 20;
}
// 在接口中使用
@get list(...PageRequest): ApiResponse<DataRow[]>;
4. 错误处理
所有接口统一返回 ApiResponse<T> 类型:
@get
getMetadata(): ApiResponse<Metadata>;
5. 版本控制
- 在路径中包含版本号:
/api/v1 - 重大变更时增加版本号
- 保持向后兼容性
6. 文档注释
/**
* 中文说明
*
* English description
*/
@summary("简短摘要")
@doc("详细说明")
扩展建议
添加新的文档类型
- 实现对应的 Provider 接口
- 注册到路由系统
- 无需修改 TypeSpec 定义
添加新的字段类型
- 在
FieldType枚举添加新类型 - 在
Valueunion 添加对应的值类型 - 更新字段类型文档
添加新的视图类型
- 在
ViewType枚举添加新类型 - 定义视图配置模型
- 实现前端渲染逻辑
添加新的事件类型
- 在 Webhook 事件枚举添加
- 定义事件载荷结构
- 实现事件触发逻辑
贡献指南
提交代码
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交变更 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 开启 Pull Request
代码规范
- 遵循现有的代码风格
- 添加适当的注释(中英文)
- 更新相关文档
- 确保 TypeSpec 编译通过
提交信息规范
type(scope): subject
body
footer
类型:
feat: 新功能fix: 修复 bugdocs: 文档更新style: 代码格式refactor: 重构test: 测试chore: 构建/工具
示例:
feat(api): 添加 Webhook 支持
- 添加 Webhook 管理接口
- 支持 20+ 种事件类型
- 实现 HMAC 签名验证
Closes #123