mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-28 03:06:38 +08:00
b0fe40142a
* Rebrand MMTL to MeBox across codebase and assets Rename the project display name, Go module path, environment variable prefix (MEBOX_*), Docker image references, and UI branding from MMTL/mmtl to MeBox/mebox. Replace logo assets with the new MeBox icon and keep legacy SQLite migration support for existing mmtl.db deployments. Co-authored-by: truewhile <truewhile@users.noreply.github.com> * Fix logo icons: use cube-only crop without truncated text Previous icon generation cropped too much of the source image, including partial MeBox wordmark text that was cut off in square icon containers. Regenerate logo-64/192/512, favicon, and SVG from cube-only region. Co-authored-by: truewhile <truewhile@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: truewhile <truewhile@users.noreply.github.com>
79 lines
1.9 KiB
Go
79 lines
1.9 KiB
Go
// Package config 加载分层配置:默认值、配置文件和环境变量。
|
|
//
|
|
// 优先级(低 -> 高):
|
|
// 1. 内置默认值
|
|
// 2. 工作目录中的 config.yaml(嵌套格式)
|
|
// 3. config/*.yaml 分片文件(按模块)
|
|
// 4. 以 MEBOX_ 为前缀的环境变量
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// EnvPrefix 是所有环境变量驱动的覆盖使用的前缀。
|
|
const EnvPrefix = "MeBox"
|
|
|
|
// Load 从默认值 / 文件 / 环境读取配置。
|
|
//
|
|
// 即使没有文件也始终返回可用的 Config。
|
|
func Load() (*Config, error) {
|
|
v := viper.New()
|
|
setDefaults(v)
|
|
|
|
v.SetConfigName("config")
|
|
v.SetConfigType("yaml")
|
|
v.AddConfigPath(".")
|
|
v.AddConfigPath("./config")
|
|
if err := v.ReadInConfig(); err != nil {
|
|
var notFound viper.ConfigFileNotFoundError
|
|
if !asConfigFileNotFound(err, ¬Found) {
|
|
return nil, fmt.Errorf("read main config: %w", err)
|
|
}
|
|
}
|
|
|
|
// 合并 ./config/*.yaml 下的分片文件。
|
|
if entries, err := os.ReadDir("config"); err == nil {
|
|
for _, e := range entries {
|
|
if e.IsDir() || !strings.HasSuffix(e.Name(), ".yaml") {
|
|
continue
|
|
}
|
|
s := viper.New()
|
|
s.SetConfigFile(filepath.Join("config", e.Name()))
|
|
if err := s.ReadInConfig(); err == nil {
|
|
_ = v.MergeConfigMap(s.AllSettings())
|
|
}
|
|
}
|
|
}
|
|
|
|
v.SetEnvPrefix(EnvPrefix)
|
|
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
|
v.AutomaticEnv()
|
|
|
|
cfg := &Config{}
|
|
if err := v.Unmarshal(cfg); err != nil {
|
|
return nil, fmt.Errorf("decode config: %w", err)
|
|
}
|
|
if err := cfg.normalize(); err != nil {
|
|
return nil, err
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
// asConfigFileNotFound 是 errors.As 的小辅助函数,避免在这个短文件中导入 errors。
|
|
func asConfigFileNotFound(err error, target *viper.ConfigFileNotFoundError) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
if v, ok := err.(viper.ConfigFileNotFoundError); ok {
|
|
*target = v
|
|
return true
|
|
}
|
|
return false
|
|
}
|