fix(commands): 修复路由顺序导致 /content 端点被遮蔽的问题

- 将 /:name{.+}/execute 和 /:name{.+}/content 路由移到 /:name{.+} 之前
- Hono 的 {.+} 模式会贪婪匹配,导致 /test/content 被解析为 name='test/content'
- 更新测试用例以正确测试 /content 端点功能
This commit is contained in:
2025-12-15 00:17:22 +08:00
parent c44527a890
commit 67e129fce2
2 changed files with 122 additions and 102 deletions
@@ -305,18 +305,16 @@ describe('Commands Route', () => {
});
describe('GET /commands/:name/content - 获取命令完整内容', () => {
// Note: Due to Hono route matching, /:name{.+} matches before /:name{.+}/content
// So /test/content is interpreted as getting command "test/content" via the detail route
// This is a known issue in the source code - the /content endpoint is shadowed
it('路由被 /:name{.+} 遮蔽,实际请求 test/content 作为命令名', async () => {
// The request goes to GET /:name{.+} with name="test/content"
// Not to GET /:name{.+}/content
mockCommandRegistry.get.mockReturnValue({
name: 'test/content',
description: 'A command with /content in name',
template: 'echo test',
source: 'project',
it('获取成功,返回包含 template 的完整内容', async () => {
mockCommandManager.getContent.mockResolvedValue({
success: true,
data: {
name: 'test',
description: 'Test command',
template: 'echo test',
source: 'project',
sourcePath: '/test/.claude/commands/test.md',
},
});
const res = await app.request('/commands/test/content');
@@ -324,21 +322,40 @@ describe('Commands Route', () => {
expect(res.status).toBe(200);
expect(json.success).toBe(true);
// The detail route returns hasTemplate, not template
expect(json.data.hasTemplate).toBe(true);
expect(json.data.template).toBeUndefined();
expect(json.data.template).toBe('echo test');
expect(json.data.name).toBe('test');
});
it('当命令不存在时返回 404', async () => {
// This also goes through GET /:name{.+} with name="non-existent/content"
mockCommandRegistry.get.mockReturnValue(undefined);
it('支持包含斜杠的命令名', async () => {
mockCommandManager.getContent.mockResolvedValue({
success: true,
data: {
name: 'deploy/staging',
template: 'deploy to staging',
source: 'project',
},
});
const res = await app.request('/commands/deploy/staging/content');
const json = await res.json();
expect(res.status).toBe(200);
expect(json.success).toBe(true);
expect(json.data.template).toBe('deploy to staging');
});
it('命令不存在返回 404', async () => {
mockCommandManager.getContent.mockResolvedValue({
success: false,
error: 'Command not found: non-existent',
});
const res = await app.request('/commands/non-existent/content');
const json = await res.json();
expect(res.status).toBe(404);
expect(json.success).toBe(false);
expect(json.error).toContain('non-existent/content');
expect(json.error).toContain('not found');
});
});