Files
router/agent/gen/index.ts

206 lines
5.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Generated by build script
export const readme = `# router
一个轻量级的路由框架,支持链式调用、中间件、嵌套路由等功能。
## 快速开始
\`\`\`ts
import { App } from '@kevisual/router';
const app = new App();
app.listen(4002);
app
.route({ path: 'demo', key: '02' })
.define(async (ctx) => {
ctx.body = '02';
})
.addTo(app);
app
.route({ path: 'demo', key: '03' })
.define(async (ctx) => {
ctx.body = '03';
})
.addTo(app);
\`\`\`
## 核心概念
### RouteContext 属性说明
在 route handler 中,你可以通过 \`ctx\` 访问以下属性:
| 属性 | 类型 | 说明 |
|------|------|------|
| \`query\` | \`object\` | 请求参数,会自动合并 payload |
| \`body\` | \`number \\| string \\| Object\` | 响应内容 |
| \`code\` | \`number\` | 响应状态码,默认为 200 |
| \`message\` | \`string\` | 响应消息 |
| \`state\` | \`any\` | 状态数据,可在路由间传递 |
| \`appId\` | \`string\` | 应用标识 |
| \`currentPath\` | \`string\` | 当前路由路径 |
| \`currentKey\` | \`string\` | 当前路由 key |
| \`currentRoute\` | \`Route\` | 当前 Route 实例 |
| \`progress\` | \`[string, string][]\` | 路由执行路径记录 |
| \`nextQuery\` | \`object\` | 传递给下一个路由的参数 |
| \`end\` | \`boolean\` | 是否提前结束路由执行 |
| \`app\` | \`QueryRouter\` | 路由实例引用 |
| \`error\` | \`any\` | 错误信息 |
| \`index\` | \`number\` | 当前路由执行深度 |
| \`needSerialize\` | \`boolean\` | 是否需要序列化响应数据 |
### 上下文方法
| 方法 | 参数 | 说明 |
|------|------|------|
| \`ctx.call(msg, ctx?)\` | \`{ path, key?, payload?, ... } \\| { id }\` | 调用其他路由,返回完整 context |
| \`ctx.run(msg, ctx?)\` | \`{ path, key?, payload? }\` | 调用其他路由,返回 \`{ code, data, message }\` |
| \`ctx.forward(res)\` | \`{ code, data?, message? }\` | 设置响应结果 |
| \`ctx.throw(code?, message?, tips?)\` | - | 抛出自定义错误 |
## 完整示例
\`\`\`ts
import { App } from '@kevisual/router';
const app = new App();
app.listen(4002);
// 基本路由
app
.route({ path: 'user', key: 'info' })
.define(async (ctx) => {
// ctx.query 包含请求参数
const { id } = ctx.query;
ctx.body = { id, name: '张三' };
ctx.code = 200;
})
.addTo(app);
// 使用 state 在路由间传递数据
app
.route({ path: 'order', key: 'create' })
.define(async (ctx) => {
ctx.state = { orderId: '12345' };
})
.addTo(app);
app
.route({ path: 'order', key: 'pay' })
.define(async (ctx) => {
// 可以获取前一个路由设置的 state
const { orderId } = ctx.state;
ctx.body = { orderId, status: 'paid' };
})
.addTo(app);
// 链式调用
app
.route({ path: 'product', key: 'list' })
.define(async (ctx) => {
ctx.body = [{ id: 1, name: '商品A' }];
})
.addTo(app);
// 调用其他路由
app
.route({ path: 'dashboard', key: 'stats' })
.define(async (ctx) => {
// 调用 user/info 路由
const userRes = await ctx.run({ path: 'user', key: 'info', payload: { id: 1 } });
// 调用 product/list 路由
const productRes = await ctx.run({ path: 'product', key: 'list' });
ctx.body = {
user: userRes.data,
products: productRes.data
};
})
.addTo(app);
// 使用 throw 抛出错误
app
.route({ path: 'admin', key: 'delete' })
.define(async (ctx) => {
const { id } = ctx.query;
if (!id) {
ctx.throw(400, '缺少参数', 'id is required');
}
ctx.body = { success: true };
})
.addTo(app);
\`\`\`
## 中间件
\`\`\`ts
import { App, Route } from '@kevisual/router';
const app = new App();
// 定义中间件
app.route({
id: 'auth-example',
description: '权限校验中间件'
}).define(async(ctx) => {
const token = ctx.query.token;
if (!token) {
ctx.throw(401, '未登录', '需要 token');
}
// 验证通过,设置用户信息到 state
ctx.state.tokenUser = { id: 1, name: '用户A' };
}).addTo(app);
// 使用中间件(通过 id 引用)
app
.route({ path: 'admin', key: 'panel', middleware: ['auth-example'] })
.define(async (ctx) => {
// 可以访问中间件设置的 state
const { tokenUser } = ctx.state;
ctx.body = { tokenUser };
})
.addTo(app);
\`\`\`
## 注意事项
1. **path 和 key 的组合是路由的唯一标识**,同一个 path+key 只能添加一个路由,后添加的会覆盖之前的。
2. **ctx.call vs ctx.run**
- \`call\` 返回完整 context包含所有属性
- \`run\` 返回 \`{ code, data, message }\` 格式data 即 body
3. **ctx.throw 会自动结束执行**,抛出自定义错误。
4. **state 不会自动继承**,每个路由的 state 是独立的,除非显式传递或使用 nextRoute。
5. **payload 会自动合并到 query**,调用 \`ctx.run({ path, key, payload })\`payload 会合并到 query。
6. **nextQuery 用于传递给 nextRoute**,在当前路由中设置 \`ctx.nextQuery\`,会在执行 nextRoute 时合并到 query。
7. **避免 nextRoute 循环调用**,默认最大深度为 40 次,超过会返回 500 错误。
8. **needSerialize 默认为 true**,会自动对 body 进行 JSON 序列化和反序列化。
9. **progress 记录执行路径**,可用于调试和追踪路由调用链。
10. **中间件找不到会返回 404**,错误信息中会包含找不到的中间件列表。
`;
export const examples_base = `# 最基本的用法
\`\`\`ts
import { App } from '@kevisual/router';
const app = new App();
app.listen(4002);
app
.route({ path: 'demo', key: '02' })
.define(async (ctx) => {
ctx.body = '02';
})
.addTo(app);
\`\`\``;