refactor(cfg): Restructure database configuration and initialization flow

- Replace separate DB/DSN fields with unified config.Database struct
    - Remove cfg/db.go and move DB client to config.Database.Client()
    - Update auth to use event-driven initialization via vb.init.auth event
    - Refactor models initialization to use event system (vb.init.settings/oauth/admin)
    - Update CLI to use event.Start() instead of manual InitDB() call
    - Fix auth_test.go to use new DB config structure
    - Update agents.md documentation with new CLI flags format
master
veypi 1 week ago
parent 23c7f6cb7a
commit 4a57017067

@ -11,8 +11,8 @@
```bash
//重置数据库
rm /tmp/vb.sqlite && go run cli/main.go -db=sqlit -dsn /tmp/vb.sqlite db migrate
go run cli/main.go -db=sqlit -dsn /tmp/vb.sqlite -p 4000
rm /tmp/vb.sqlite
go run cli/main.go -db.type=sqlite -db.dsn /tmp/vb.sqlite -p 4000
```
可以通过 <http://localhost:4000/\_api.json> 查看接口列表

@ -17,6 +17,7 @@ import (
"github.com/veypi/vbase/libs/cache"
"github.com/veypi/vbase/models"
"github.com/veypi/vigo"
"github.com/veypi/vigo/contrib/event"
)
// Auth 权限管理接口
@ -91,6 +92,10 @@ func init() {
"oauth-client:update",
"oauth-client:delete",
)
// 注册权限初始化回调到 cfg 包
// 这样 models.InitDB() 可以在合适的时机调用,避免循环依赖
event.Add("vb.init.auth", Factory.init)
}
type authFactory struct {

@ -14,8 +14,8 @@ import (
// setupTestDB 初始化测试数据库
func setupTestDB() {
// 使用 SQLite 内存模式
cfg.Config.DB = "sqlite"
cfg.Config.DSN = fmt.Sprintf("file::memory:?cache=shared&_time=%d", time.Now().UnixNano())
cfg.Config.DB.Type = "sqlite"
cfg.Config.DB.Type = fmt.Sprintf("file::memory:?cache=shared&_time=%d", time.Now().UnixNano())
// 初始化数据库表
if err := models.AllModels.AutoMigrate(cfg.DB()); err != nil {

@ -19,10 +19,9 @@ import (
// Options 本地配置选项(启动时加载,修改需重启)
type Options struct {
// === 基础设施(必须)===
DSN string `json:"dsn" usage:"数据库连接字符串"` // Data Source Name
DB string `json:"db" usage:"数据库类型: mysql, postgres, sqlite"`
Redis config.Redis `json:"redis" usage:"Redis 配置addr: memory 使用内存模式"`
Key config.Key `json:"key" usage:"系统密钥,用于加密敏感数据(建议 32 位以上)"`
DB config.Database `json:"db"`
Redis config.Redis `json:"redis" usage:"Redis 配置addr: memory 使用内存模式"`
Key config.Key `json:"key" usage:"系统密钥,用于加密敏感数据(建议 32 位以上)"`
// === 文件存储 ===
StoragePath string `json:"storage_path" usage:"文件存储路径"`
@ -53,8 +52,10 @@ type InitAdminConfig struct {
// Config 全局配置实例
var Config = &Options{
DB: "mysql",
DSN: "root:123456@tcp(127.0.0.1:3306)/vbase?charset=utf8&parseTime=True&loc=Local",
DB: config.Database{
Type: "mysql",
DSN: "root:123456@tcp(127.0.0.1:3306)/vbase?charset=utf8&parseTime=True&loc=Local",
},
Redis: config.Redis{
Addr: "memory",
},
@ -72,3 +73,5 @@ var Config = &Options{
Email: "admin@example.com",
},
}
var DB = Config.DB.Client

@ -1,41 +0,0 @@
//
// db.go
// Copyright (C) 2024 veypi <i@veypi.com>
// 2025-03-04 16:08:06
// Distributed under terms of the MIT license.
//
package cfg
import (
"github.com/glebarez/sqlite"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var db *gorm.DB
func DB() *gorm.DB {
if db == nil {
var err error
var conn gorm.Dialector
switch Config.DB {
case "mysql":
conn = mysql.Open(Config.DSN)
case "postgres":
conn = postgres.Open(Config.DSN)
default:
conn = sqlite.Open(Config.DSN)
}
db, err = gorm.Open(conn,
&gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
if err != nil {
panic(err)
}
}
return db
}

@ -12,6 +12,7 @@ import (
"github.com/veypi/vbase/cfg"
"github.com/veypi/vbase/models"
"github.com/veypi/vigo"
"github.com/veypi/vigo/contrib/event"
"github.com/veypi/vigo/flags"
"github.com/veypi/vigo/logv"
)
@ -35,7 +36,6 @@ func init() {
cmdMain.Command = runWeb
cmdDB.SubCommand("migrate", "migrate database").Command = models.Migrate
cmdDB.SubCommand("drop", "drop database").Command = models.Drop
cmdDB.SubCommand("init", "init db data").Command = models.InitDB
}
func main() {
@ -47,11 +47,8 @@ func main() {
}
func runWeb() error {
// 初始化权限系统
if err := vbase.Auth.Init(); err != nil {
return err
}
models.Migrate()
event.Start()
server, err := vigo.New(vigo.WithHost(cliOpts.Host), vigo.WithPort(cliOpts.Port))
if err != nil {
return err

@ -13,6 +13,7 @@ import (
"github.com/veypi/vbase/cfg"
"github.com/veypi/vbase/libs/crypto"
"github.com/veypi/vigo"
"github.com/veypi/vigo/contrib/event"
)
var AllModels = &vigo.ModelList{}
@ -42,6 +43,9 @@ func init() {
AllModels.Add(&VerificationCode{})
AllModels.Add(&EmailLog{})
AllModels.Add(&OAuthProvider{})
event.Add("vb.init.settings", InitSettings)
event.Add("vb.init.oauth", InitOAuthProviders)
event.Add("vb.init.admin", initAdminUser, event.After("vb.init.auth"))
}
func Migrate() error {
@ -52,24 +56,6 @@ func Drop() error {
return AllModels.AutoDrop(cfg.DB())
}
func InitDB() error {
// 1. 初始化系统配置
if err := InitSettings(); err != nil {
return fmt.Errorf("init settings failed: %w", err)
}
// 2. 初始化 OAuth 提供商
if err := InitOAuthProviders(); err != nil {
return fmt.Errorf("init oauth providers failed: %w", err)
}
// 3. 检查是否需要创建初始管理员
if err := initAdminUser(); err != nil {
return fmt.Errorf("init admin user failed: %w", err)
}
return nil
}
// initAdminUser 如果用户表为空且配置了 init_admin则自动创建管理员
func initAdminUser() error {
db := cfg.DB()

Loading…
Cancel
Save