347 lines
12 KiB
Markdown
347 lines
12 KiB
Markdown
# atomctl v2 命令行工具
|
||
|
||
Atom 应用脚手架与代码生成工具。基于 cobra 构建,集成新项目/模块脚手架、HTTP 路由与 Provider 生成、数据库迁移与模型生成、Swagger 文档、Proto 生成与代码格式化等能力。
|
||
|
||
## 安装与使用
|
||
|
||
- 安装已发布版本:`go install go.ipao.vip/atomctl/v2@latest`
|
||
- 本地构建:`go build -o atomctl .`
|
||
- 开发运行:`go run . --help`
|
||
- 运行测试:`go test ./...`
|
||
|
||
运行 `atomctl --help` 查看总览。
|
||
|
||
## 顶级命令
|
||
|
||
- `new`:项目脚手架与代码模板初始化
|
||
- `gen`:代码生成(route/provider/model/enum/service)
|
||
- `migrate`:数据库迁移(pressly/goose)
|
||
- `swag`:Swagger 文档生成与格式化
|
||
- `fmt`:Go 代码格式化(自动安装/调用 gofumpt)
|
||
- `buf`:Proto 代码生成(自动安装 buf 并执行 generate)
|
||
|
||
---
|
||
|
||
## new 脚手架
|
||
|
||
创建项目/组件初始文件。该命令组带有以下持久化参数(所有子命令通用):
|
||
|
||
- `--force, -f`:覆盖已存在文件/目录
|
||
- `--dry-run`:仅预览生成动作,不写入文件
|
||
- `--dir`:输出基目录(默认 `.`)
|
||
|
||
子命令:
|
||
|
||
### new project (别名:p)
|
||
|
||
- 功能:基于内置模板创建新项目,或在已有 go.mod 的项目内进行就地初始化
|
||
- 参数:
|
||
- `[module]`:可选。在空目录中创建项目时必填(例如 `github.com/acme/myapp`);在已有项目内可省略
|
||
- 选项:
|
||
- `--force`:当目标目录存在时强制覆盖
|
||
- 行为说明:
|
||
- 识别模板中的隐藏文件占位(模板以 `-` 开头的文件名会渲染为 `.` 前缀,例如 `-.gitignore` -> `.gitignore`)
|
||
- 支持 `.tpl` 渲染与 `.raw` 直写;也支持文件内通过 `atomctl:mode=tpl|raw` 指示
|
||
- 在当前模块内执行时会跳过覆盖已有的 `go.mod`
|
||
- 生成后提示后续步骤(`cd` 与 `go mod tidy`)
|
||
|
||
示例:
|
||
|
||
```
|
||
atomctl new project github.com/acme/demo
|
||
atomctl new -f --dir ./playground project github.com/acme/demo
|
||
atomctl new project # 在已有 go.mod 的项目中就地初始化
|
||
```
|
||
|
||
### new provider
|
||
|
||
- 功能:创建 Provider 脚手架到 `providers/<name>`
|
||
- 参数:
|
||
- `<name>`:可选。省略名称时会列出可用的内置预置 providers 供选择
|
||
- 选项:继承 `--dry-run`、`--dir`
|
||
- 行为:
|
||
- 若 `<name>` 与内置 `templates/providers/<name>` 目录同名,则渲染该目录
|
||
- 否则回退渲染 `templates/providers/default` 到 `providers/<name>`
|
||
|
||
示例:
|
||
|
||
```
|
||
atomctl new provider # 列出可用预置 providers
|
||
atomctl new provider redis # 渲染 providers/redis 预置
|
||
atomctl new provider email # 未命中预置,回退 default 渲染到 providers/email
|
||
atomctl new --dry-run --dir ./demo provider cache
|
||
```
|
||
|
||
### new event (别名:e)
|
||
|
||
- 功能:生成事件发布者与订阅者模板
|
||
- 参数:
|
||
- `<name>`:必填,事件名(驼峰自动转换为 snake 作为 topic)
|
||
- 选项:
|
||
- `--only`:仅生成某一侧,`publisher` 或 `subscriber`
|
||
- 继承 `--dry-run`、`--dir`
|
||
- 行为说明:
|
||
- 生成 publisher 到 `app/events/publishers/<snake>.go`
|
||
- 生成 subscriber 到 `app/events/subscribers/<snake>.go`
|
||
- 追加常量到 `app/events/topics.go`:`const Topic{Name} = "event:<snake>"`(避免重复)
|
||
|
||
示例:
|
||
|
||
```
|
||
atomctl new event UserCreated
|
||
atomctl new event UserCreated --only=publisher
|
||
```
|
||
|
||
### new job
|
||
|
||
- 功能:生成任务模板文件;支持可选的定时任务模板
|
||
- 参数:
|
||
- `<name>`:必填,任务名
|
||
- 选项:
|
||
- 继承 `--dry-run`、`--dir`
|
||
- `--cron`:除生成 `app/jobs/<snake>.go` 外,额外生成 `app/jobs/cron_<snake>.go`
|
||
|
||
示例:
|
||
|
||
```
|
||
atomctl new job SendDailyReport # 生成 app/jobs/send_daily_report.go
|
||
atomctl new job SendDailyReport --cron # 同时生成 cron 版本 app/jobs/cron_send_daily_report.go
|
||
```
|
||
|
||
> 说明:代码中已存在 `new module` 实现,但当前未注册到 `new` 子命令中(处于弃用状态)。
|
||
|
||
---
|
||
|
||
## gen 代码生成
|
||
|
||
命令组持久化参数:
|
||
|
||
- `-c, --config`:数据库配置文件路径(默认 `config.toml`),用于 `gen model`
|
||
- 执行完成后自动调用 `atomctl fmt` 格式化生成代码
|
||
|
||
子命令:
|
||
|
||
### gen model (别名:m)
|
||
|
||
- 功能:连接 PostgreSQL,基于配置生成 GORM 模型与相关文件(委托 `go.ipao.vip/gen`)到 `./database`,并读取 `./database/.transform.yaml` 做类型/命名转换
|
||
- 配置文件 `[Database]` 字段:
|
||
- `Username`、`Password`、`Database`、`Host`、`Port`、`Schema`、`SslMode`、`TimeZone`
|
||
- 示例 `config.toml`:
|
||
|
||
```toml
|
||
[Database]
|
||
Host = "127.0.0.1"
|
||
Port = 5432
|
||
Username = "postgres"
|
||
Password = "secret"
|
||
Database = "app"
|
||
Schema = "public"
|
||
SslMode = "disable"
|
||
TimeZone = "Asia/Shanghai"
|
||
```
|
||
|
||
示例:
|
||
|
||
```
|
||
atomctl gen -c config.toml model
|
||
```
|
||
|
||
### gen route
|
||
|
||
- 功能:扫描项目 `app/http` 目录的控制器,解析注释生成 `routes.gen.go`
|
||
- 参数:
|
||
- `--path`:扫描根目录(默认当前工作目录);也可作为位置参数传入项目根路径
|
||
- 注释规则:
|
||
- `@Router <path> [<method>]` 指定路由与方法,如 `@Router /users/:id [get]`
|
||
- `@Bind <name> (<position>) key(<key>) [model(<field[:field_type]>)]`
|
||
- position 枚举:`path|query|body|header|cookie|local|file`
|
||
- model() 定义形式:
|
||
1) `model()` 默认字段 `id`,类型 `int`
|
||
2) `model(id)` 指定字段 `id`,类型默认 `int`
|
||
3) `model(id:int)` 指定字段 `id`,类型 `int`
|
||
- 示例:
|
||
- `@Bind id path key(id)`(PathParam 绑定)
|
||
- `@Bind page query key(page)`(QueryParam 绑定)
|
||
- `@Bind auth header key(Authorization)`
|
||
- `@Bind file file key(upload)`(文件)
|
||
- `@Bind user path key(id) model(id:int)`(从路径 id 加载模型,按 id:int 查询)
|
||
|
||
示例:
|
||
|
||
```go
|
||
// UserController
|
||
// @Router /users/:id [get]
|
||
// @Bind id path key(id) model(id:int)
|
||
func (c *UserController) Show(ctx context.Context, id int) (*User, error) { /* ... */ }
|
||
```
|
||
|
||
执行:
|
||
|
||
```
|
||
atomctl gen route --path .
|
||
```
|
||
|
||
> 注意:生成完成后会自动触发 `gen provider` 以补全依赖注入。
|
||
|
||
#### Bind 参数类型与位置支持
|
||
|
||
- 标量类型(scalar):`string`、`bool`、`int|int8|int16|int32|int64`、`uint|uint8|uint16|uint32|uint64`、`float32|float64`
|
||
- 位置与类型支持:
|
||
- `path`:支持标量;也支持通过 `model()` 从路径值加载模型记录(推荐标量或 model 查找)。
|
||
- 示例:`@Bind id path key(id)`、`@Bind user path key(id) model(id:int)`
|
||
- `query`:支持标量或结构体(结构体将按字段名/标签聚合解析查询参数)。
|
||
- 示例:`@Bind page query key(page)`、`@Bind filter query key(q)` 或 `@Bind opts query key(_)`
|
||
- `header`:支持标量或结构体(按字段名/标签解析请求头)。
|
||
- 示例:`@Bind auth header key(Authorization)`
|
||
- `cookie`:支持标量;`string` 有快捷写法(`CookieParam`)。
|
||
- 示例:`@Bind sid cookie key(session_id)`
|
||
- `body`:支持结构体或标量(通常用于 JSON 体,推荐结构体)。
|
||
- 示例:`@Bind input body key(_)`
|
||
- `file`:固定类型为 `multipart.FileHeader`,用于文件上传。
|
||
- 示例:`@Bind file file key(upload)`
|
||
- `local`:任意类型(从上下文本地存取,而非请求来源)。
|
||
- 示例:`@Bind user local key(currentUser)`
|
||
|
||
|
||
### gen provider (别名:p)
|
||
|
||
- 功能:扫描 Go 源码查找带 `@provider` 注释的结构体,生成 `provider.gen.go` 实现依赖注入与分组注册
|
||
- 注释语法:`@provider(<mode>):[except|only] [returnType] [group]`
|
||
- `mode`:`grpc|event|job|cronjob|model`(留空为默认)
|
||
- `:only`:仅注入标注了结构体字段 tag `inject:"true"` 的依赖
|
||
- `:except`:注入全部非标量字段,除非字段 tag `inject:"false"`
|
||
- `returnType`:Provide 返回类型(如 `contracts.Initial`)
|
||
- `group`:归属分组(如 `atom.GroupInitial`)
|
||
- 行为特性:
|
||
- 自动分析字段类型与 import,忽略标量类型
|
||
- `grpc`:注入 `providers/grpc.Grpc`,设置 `GrpcRegisterFunc`
|
||
- `event`:注入 `providers/event.PubSub`
|
||
- `job|cronjob`:注入 `providers/job.Job` 并引入 `github.com/riverqueue/river`
|
||
- `model`:标记需要 `Prepare` 钩子
|
||
|
||
示例:
|
||
|
||
```go
|
||
// @provider(job):only contracts.Initial atom.GroupInitial
|
||
type UserJob struct {
|
||
// 仅在 only 模式下注入
|
||
Repo *repo.UserRepo `inject:"true"`
|
||
Log *log.Logger `inject:"true"`
|
||
}
|
||
```
|
||
|
||
执行:`atomctl gen provider`(支持在任意子目录执行,自动写入对应包下的 `provider.gen.go`)
|
||
|
||
### gen enum (别名:e)
|
||
|
||
- 功能:在工程内扫描包含 `ENUM(...)` 且带 `swagger:enum` 的类型定义文件,为每个文件生成 `*.gen.go`
|
||
- 选项:
|
||
- `-f, --flag`:生成 `flag.Value` 支持(默认 true)
|
||
- `-m, --marshal`:生成 JSON 编解码支持
|
||
- `-s, --sql`:生成 `database/sql` 相关驱动与 Null 支持(默认 true)
|
||
|
||
示例:`atomctl gen enum -m -s`
|
||
|
||
### gen service
|
||
|
||
- 功能:根据 `app/services` 下的服务文件聚合生成 `services.gen.go`
|
||
- 选项:
|
||
- `--path`:服务目录(默认 `./app/services`)
|
||
|
||
示例:`atomctl gen service --path ./app/services`
|
||
|
||
---
|
||
|
||
## migrate 数据库迁移(goose)
|
||
|
||
- 用法:`atomctl migrate [action] [args...]`
|
||
- 支持 action:`up|up-by-one|up-to|create|down|down-to|fix|redo|reset|status|version`
|
||
- 选项:
|
||
- `-c, --config`:数据库配置文件(默认 `config.toml`,读取 `[Database]`)
|
||
- `--dir`:迁移目录(默认 `database/migrations`)
|
||
- `--table`:迁移版本表名(默认 `migrations`)
|
||
- 说明:
|
||
- 执行 `create` 时若未指定脚本类型,会自动追加 `sql` 类型
|
||
- 连接配置同上 `gen model` 的 `[Database]` 字段
|
||
|
||
示例:
|
||
|
||
```
|
||
atomctl migrate status
|
||
atomctl migrate up
|
||
atomctl migrate create add_users_table
|
||
```
|
||
|
||
---
|
||
|
||
## swag 文档
|
||
|
||
### swag init (别名:i)
|
||
|
||
- 功能:生成 Swagger 文档(go/json/yaml)
|
||
- 选项:
|
||
- `--dir`:项目根目录(默认 `.`)
|
||
- `--out`:输出目录(默认 `docs`)
|
||
- `--main`:主入口文件(默认 `main.go`)
|
||
|
||
示例:`atomctl swag init --dir . --out docs --main cmd/server/main.go`
|
||
|
||
### swag fmt (别名:f)
|
||
|
||
- 功能:格式化接口注释与路由
|
||
- 选项:
|
||
- `--dir`:扫描目录(默认 `./app/http`)
|
||
- `--main`:主入口文件(默认 `main.go`)
|
||
|
||
示例:`atomctl swag fmt --dir ./app/http --main main.go`
|
||
|
||
---
|
||
|
||
## fmt 代码格式化
|
||
|
||
- 功能:调用 `gofumpt -extra` 格式化全项目;若未安装将自动 `go install mvdan.cc/gofumpt@latest`
|
||
- 选项:
|
||
- `--check`:仅检查不写入,输出未格式化文件列表
|
||
- `--path`:格式化范围(默认 `.`)
|
||
|
||
示例:
|
||
|
||
```
|
||
atomctl fmt # 写入格式化
|
||
atomctl fmt --check --path ./pkg
|
||
```
|
||
|
||
---
|
||
|
||
## buf Proto 生成
|
||
|
||
- 功能:检查/安装 `buf` 并执行 `buf generate`(在指定目录)
|
||
- 选项:
|
||
- `--dir`:执行目录(默认 `.`)
|
||
- `--dry-run`:仅预览不执行
|
||
- 说明:若找不到 `buf.yaml` 会给出提示但仍尝试生成
|
||
|
||
示例:`atomctl buf --dir ./proto`
|
||
|
||
---
|
||
|
||
## 配置与约定
|
||
|
||
- Go 版本:1.23+
|
||
- 数据库配置段落:`[Database]`(被 `gen model` 与 `migrate` 读取)
|
||
- 代码生成默认位置:
|
||
- 路由:`app/http/**/routes.gen.go`
|
||
- Provider:每个包内的 `provider.gen.go`
|
||
- 模型:`./database`(含 `.transform.yaml`)
|
||
- Enum:原文件同目录生成 `*.gen.go`
|
||
- Services:`app/services/services.gen.go`
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
- 路由未生成?确保控制器方法注释包含 `@Router`,且形参通过 `@Bind` 标注位置/键名。
|
||
- Provider 未注入期望字段?检查 `@provider:only|:except` 与字段 tag `inject:"true|false"` 的组合是否正确。
|
||
- 执行 `fmt` 报 gofumpt 不存在?工具会自动安装,如仍失败请检查网络与 `GOBIN`/`PATH`。
|
||
- `buf generate` 找不到命令?工具会自动安装 buf,若仍失败请手动安装或检查网络代理。
|