Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
85 changes: 85 additions & 0 deletions .agents/rules/git-commit.mdc.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
description: 起草或生成 git commit message 时使用(Conventional Commits + TaskID)
alwaysApply: false
---

# Git Commit Message 规范

对齐 `@commitlint/config-conventional` 与 Conventional Commits 1.0.0。起草 / 执行 `git commit` 时必须遵循本规范。

## 格式

```text
<type>(<scope>): <subject> <TaskID>

<body>

<footer>
```

- header / body / footer 之间空一行
- `scope`、`TaskID`、`body`、`footer` 均可省略;有关联工单时必须带 `TaskID`
- `subject` ≤ 50 字符,祈使语气,首字母小写、句末不加句号
- `body` 每行尽量 ≤ 72 字符,可多段、可用列表

## type

| type | 含义 |
|------|------|
| `feat` | 新功能 |
| `fix` | 修 bug |
| `perf` | 性能优化(仅限性能,不含一般改进) |
| `docs` | 文档 |
| `style` | 代码格式(不影响运行的变动) |
| `refactor` | 重构(非新功能、非修 bug),运维部署变更(端口号、环境变量、配置文件等) |
| `test` | 增加或修正测试 |
| `build` | 构建系统或外部依赖变更(pnpm、tsconfig、依赖升级等) |
| `ci` | CI 配置与脚本变更(GitHub Actions 等) |
| `chore` | 其他杂项(不改动源码与测试的维护性变动) |
| `revert` | 撤销变更(header 复述被撤销 commit 的 header,body 注明 `This reverts commit <hash>.`) |

依赖变更写成 `build(deps): ...`,不要用独立的 `deps` type。

## scope(本仓库推荐)

- `services` — `apps/services`
- `commands` — `packages/commands`
- `cli` — `bin/`
- `agents` — `.agents/`
- `deps` — 依赖升降级(配合 `build`)
- `root` — 根配置(`package.json`、pnpm workspace 等)

跨包改动可省略 scope,或用最主要影响面。

## footer

仅两种用途:

1. 不兼容变动:以 `BREAKING CHANGE: ` 开头,说明变动、理由与迁移方法;也可在 type/scope 后加 `!`(如 `feat(services)!: ...`)并配合 footer
2. 关闭缺陷:`Closes #123` / `Fixes #123`

## 正反例

```text
# 好
feat(services): add health check endpoint T123

Expose GET /api/health without auth so deploy probes
can verify the process is up.

# 好(无工单、无 body)
fix(commands): handle missing app id in apikey create

# 好(依赖变更)
build(deps): bump @axiosleo/koapp from 1.2.0 to 1.3.1

# 好(破坏性)
feat(services): require bearer prefix on openapi keys

BREAKING CHANGE: Api-Key must start with sk2a_. Old keys
need to be recreated via ${name} apikey create.

# 差
Update stuff.
fix: Fixed the bug.
```
File renamed without changes.
28 changes: 28 additions & 0 deletions .agents/rules/services-backend.mdc.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
description: apps/services 后端(koapp)模块结构与编码约定
globs: apps/services/**
alwaysApply: false
---

# services 后端约定

## 模块结构

- 业务模块三件套:`src/modules/<name>/<name>.router.ts`(路由)+ `<name>.controller.ts`(处理器)+ `<name>.model.ts`(validatorjs 校验规则与类型)
- 路由统一在 `src/modules/index.ts` 挂载,分两套 API 面:
- `/openapi`:`authMiddleware`(Bearer Api-Key,按 app_id 限定作用域);模板为空壳,业务路由在此挂载
- `/api`:admin 模块(登录/登出/资料)公开挂载,其余模块挂在 `adminAuthMiddleware`(Session)之后(当前为 app)
- `GET /api/health`:无鉴权健康检查
- 路由参数写法 `/{:id}`,校验规则挂路由第三参:`{ params/query/body: { rules } }`

## Controller

- 继承 `src/modules/controller.ts` 的 `BaseController`:
- `this.appId(ctx)` 解析应用作用域(Api-Key 强制取 key 的 app_id;admin 会话可选过滤,null = 不过滤)
- 响应用 `this.success(...)` / `this.error(status, msg)`

## 共享服务与测试

- 共享服务放 `src/services/`:`sqlite.ts`(元数据库:apps / api_keys)
- 测试与源码同目录,命名 `*.test.ts`,mocha 运行:`pnpm test`;单跑一个文件用 `pnpm test-one <路径>`
- koapp 框架 API 细节(Router / Controller / Model / 响应)见 `.cursor/skills/koapp*` 技能
File renamed without changes.
1 change: 1 addition & 0 deletions assets/skills/koapp-apps/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,4 @@ If you just need to build one server, start with the matching doc:
- Building a TCP service → [socket-server.md](socket-server.md)
- Building a WebSocket service → [websocket-server.md](websocket-server.md)
- Copy-paste-ready examples → [examples.md](examples.md)
- Typing contexts and configs in TypeScript → **koapp-typescript**
27 changes: 27 additions & 0 deletions assets/skills/koapp-apps/http-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,33 @@ router.post('/upload', async (context) => {

Install with `npm install @koa/multer` (and `@types/koa__multer` for TS).

In TypeScript, uploaded files are **not** covered by the body generic -
they live on `context.koa.request.files`. Type the route through
`KoaContext` so the multer types apply:

```typescript
import multer from '@koa/multer';
import { KoaContext, success, failed } from '@axiosleo/koapp';

type UploadContext = KoaContext<{ dir: string }> & {
params: { dir: string };
};

router.post<UploadContext>('/upload/{:dir}', async (context) => {
const upload = multer({ storage: multer.memoryStorage() });
await upload.any()(context.koa, async () => {});
const files = context.koa.request.files;
const first = Array.isArray(files) ? files[0] : undefined;
if (!first) {
failed({}, '400;Bad Data', 400);
}
success({ dir: context.params.dir, name: first.originalname });
});
```

See **koapp-typescript** for the full typed-upload recipes (single file,
multiple files, echo-as-download).

## Sessions

When `session` config is present, the framework signs the cookie with
Expand Down
1 change: 1 addition & 0 deletions assets/skills/koapp-router/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,4 @@ For a request `PUT /users/42`:
- Richer, copy-paste examples: [examples.md](examples.md)
- Building a complete HTTP server around the router: **koapp-apps**
- Sending responses from handlers: **koapp-response**
- Typed contexts and Router generics in TypeScript: **koapp-typescript**
Loading
Loading