重构:main.go 直接 import 各 internal/ 子包,删除全部 bridge

最后一步:把 main.go 里所有指向桥接小写名的引用(store / config /
blocking / bot / runtimesettings / mqttforward / web 等)改写成直接调用
internal/* 子包的导出 API,从而拆掉所有 *_bridge.go。

变更点
- main.go 顶部 import 区改为引用 11 个 internal/ 子包:auth、blocking、
  bot、config、mqttforward、runtimesettings、store、web 等。
- meshtasticFilterHook 字段类型改为 *storepkg.WriteQueue / *blockingpkg.Cache
  / *rspkg.Cache / *mqttforwardpkg.Stats;不再依赖 main 包内别名。
- mqttClientInfoFromClient 返回 storepkg.MQTTClientInfo(之前为 main 包别名)。
- run() 里 newSessionManager → auth.NewManager;newRouter → webpkg.NewRouter;
  serveHTTPUnixSocket → webpkg.ServeUnixSocket;mqttRuntimeStatus →
  webpkg.MQTTRuntimeStatus;botSendTextRequest → botpkg.SendTextRequest;
  newBlockingCache / newRuntimeSettingsCache / newMQTTForwardManager 都改为
  对应包的 New / NewManager。
- main_test.go 里的 BlockingViolationForRecord 测试改用 testutil.OpenStore
  + blockingpkg.New,全部通过 store.Store 的公开 API 构造数据,不再需要
  根目录 test_helpers_test.go。

删除根目录文件
- config.go、auth.go(已删)、blocking_bridge.go、bot_bridge.go、
  help_bridge.go、llmadmin_bridge.go、mapsource_bridge.go、
  mqttforward_bridge.go、runtime_settings_bridge.go、sign_bridge.go、
  store_bridge.go、web_bridge.go、test_helpers_test.go。

最终结果
- 根目录只剩 main.go (~370 行) 和 main_test.go (~110 行)。
- internal/ 下 13 个独立子包:auth / blocking / bot / config / help /
  llmadmin / mapsource / mqttforward / runtimesettings / sign / store /
  store/testutil / web / webutil。
- go build ./... / go test ./... 全部通过;测试数量与重构前一致;
  go build . 可以产出可执行二进制(约 50 MB)。

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-18 18:30:00 +08:00
co-authored by Claude
parent 9394aa0f4a
commit 46916d9a93
14 changed files with 70 additions and 480 deletions
-21
View File
@@ -1,21 +0,0 @@
package main
// 桥接到 internal/blocking — 让根目录其余文件可以继续使用旧名字
// blockingCache / newBlockingCache / registerAdminBlockingRoutes
// 而无须改动 main.go / web.go 等十几处调用点。
import (
"github.com/gin-gonic/gin"
blockingpkg "meshtastic_mqtt_server/internal/blocking"
)
type blockingCache = blockingpkg.Cache
func newBlockingCache(s *store) (*blockingCache, error) {
return blockingpkg.New(s)
}
func registerAdminBlockingRoutes(r gin.IRouter, s *store, b *blockingCache) {
blockingpkg.RegisterRoutes(r, s, b)
}
-31
View File
@@ -1,31 +0,0 @@
package main
// 桥接到 internal/bot — 让 main.go / web.go 中使用 botService /
// botTextSender / newBotService / newPKIKeyResolver / registerAdminBotRoutes
// 这些旧名字的代码继续可用。
import (
mqtt "github.com/mochi-mqtt/server/v2"
"github.com/gin-gonic/gin"
botpkg "meshtastic_mqtt_server/internal/bot"
)
type (
botService = botpkg.Service
botTextSender = botpkg.TextSender
botSendTextRequest = botpkg.SendTextRequest
)
func newBotService(s *store, server *mqtt.Server, key []byte) *botService {
return botpkg.NewService(s, server, key)
}
func newPKIKeyResolver(s *store) func(toNodeNum, fromNodeNum uint32) ([]byte, []byte, bool) {
return botpkg.NewPKIKeyResolver(s)
}
func registerAdminBotRoutes(r gin.IRouter, s *store, sender botTextSender) {
botpkg.RegisterRoutes(r, s, sender)
}
-43
View File
@@ -1,43 +0,0 @@
package main
import (
cryptotls "crypto/tls"
cfgpkg "meshtastic_mqtt_server/internal/config"
)
// 桥接到 internal/config — 让根目录其余文件无须修改即可继续使用旧的非导出名字。
const (
configFileName = cfgpkg.FileName
databaseDriverSQLite = cfgpkg.DriverSQLite
databaseDriverMySQL = cfgpkg.DriverMySQL
)
// 旧的小写类型名通过别名继续可用。
type (
config = cfgpkg.Config
mqttConfig = cfgpkg.MQTTConfig
tlsConfig = cfgpkg.TLSConfig
meshtasticConfig = cfgpkg.MeshtasticConfig
databaseConfig = cfgpkg.DatabaseConfig
sqliteConfig = cfgpkg.SQLiteConfig
mysqlConfig = cfgpkg.MySQLConfig
webConfig = cfgpkg.WebConfig
webAdminConfig = cfgpkg.WebAdminConfig
aiConfig = cfgpkg.AIConfig
)
func defaultConfig() *config { return cfgpkg.Default() }
func defaultConfigDir() string { return cfgpkg.DefaultDir() }
func defaultConfigPath() string { return cfgpkg.DefaultPath() }
func loadConfig(path string) (*config, error) { return cfgpkg.Load(path) }
func writeConfig(path string, cfg *config) error { return cfgpkg.Write(path, cfg) }
func validateConfig(cfg *config) error { return cfgpkg.Validate(cfg) }
func clearWebSocketPathOnUnsupportedGOOS(cfg *config, goos string) bool {
return cfgpkg.ClearWebSocketPathOnUnsupportedGOOS(cfg, goos)
}
func buildTLSConfig(cfg tlsConfig) (*cryptotls.Config, error) {
return cfgpkg.BuildTLS(cfg)
}
-16
View File
@@ -1,16 +0,0 @@
package main
// 桥接到 internal/help — 让 web.go 中的 registerHelpRoutes /
// registerAdminHelpRoutes / renderHelpMarkdown 旧名字仍可用。
import (
"github.com/gin-gonic/gin"
helppkg "meshtastic_mqtt_server/internal/help"
)
func registerHelpRoutes(r gin.IRouter, s *store) { helppkg.RegisterPublicRoutes(r, s) }
func registerAdminHelpRoutes(r gin.IRouter, s *store) { helppkg.RegisterAdminRoutes(r, s) }
func renderHelpMarkdown(markdown string) (string, error) {
return helppkg.RenderMarkdown(markdown)
}
-13
View File
@@ -1,13 +0,0 @@
package main
// 桥接到 internal/llmadmin — 让 web.go 中的 registerAdminLLMRoutes 旧名仍可用。
import (
"github.com/gin-gonic/gin"
llmadminpkg "meshtastic_mqtt_server/internal/llmadmin"
)
func registerAdminLLMRoutes(r *gin.RouterGroup, s *store) {
llmadminpkg.RegisterRoutes(r, s)
}
+54 -46
View File
@@ -14,15 +14,23 @@ import (
"syscall"
"time"
"meshtastic_mqtt_server/ai"
"meshtastic_mqtt_server/autoreply"
"meshtastic_mqtt_server/llm"
"meshtastic_mqtt_server/mqtpp"
mqtt "github.com/mochi-mqtt/server/v2"
"github.com/mochi-mqtt/server/v2/hooks/auth"
mqttauth "github.com/mochi-mqtt/server/v2/hooks/auth"
"github.com/mochi-mqtt/server/v2/listeners"
"github.com/mochi-mqtt/server/v2/packets"
"meshtastic_mqtt_server/ai"
"meshtastic_mqtt_server/autoreply"
"meshtastic_mqtt_server/internal/auth"
blockingpkg "meshtastic_mqtt_server/internal/blocking"
botpkg "meshtastic_mqtt_server/internal/bot"
configpkg "meshtastic_mqtt_server/internal/config"
mqttforwardpkg "meshtastic_mqtt_server/internal/mqttforward"
rspkg "meshtastic_mqtt_server/internal/runtimesettings"
storepkg "meshtastic_mqtt_server/internal/store"
webpkg "meshtastic_mqtt_server/internal/web"
"meshtastic_mqtt_server/llm"
"meshtastic_mqtt_server/mqtpp"
)
const (
@@ -39,10 +47,10 @@ const (
type meshtasticFilterHook struct {
mqtt.HookBase
key []byte
dbQueue *dbWriteQueue
stats *meshtasticMessageStats
blocking *blockingCache
settings *runtimeSettingsCache
dbQueue *storepkg.WriteQueue
stats *mqttforwardpkg.Stats
blocking *blockingpkg.Cache
settings *rspkg.Cache
pkiResolver func(toNodeNum, fromNodeNum uint32) ([]byte, []byte, bool)
autoAcker func(record map[string]any)
}
@@ -107,7 +115,7 @@ func (h *meshtasticFilterHook) rejectPublish(cl *mqtt.Client, pk packets.Packet,
h.dbQueue.EnqueueDiscard(record, pk.Payload, mqttClientInfoFromClient(cl))
}
func blockingViolationForRecord(blocking *blockingCache, record map[string]any) map[string]any {
func blockingViolationForRecord(blocking *blockingpkg.Cache, record map[string]any) map[string]any {
if blocking == nil || record == nil {
return nil
}
@@ -129,12 +137,12 @@ func blockingViolationForRecord(blocking *blockingCache, record map[string]any)
return nil
}
func mqttClientInfoFromClient(cl *mqtt.Client) mqttClientInfo {
func mqttClientInfoFromClient(cl *mqtt.Client) storepkg.MQTTClientInfo {
if cl == nil {
return mqttClientInfo{}
return storepkg.MQTTClientInfo{}
}
info := mqttClientInfo{
info := storepkg.MQTTClientInfo{
ClientID: cl.ID,
Username: string(cl.Properties.Username),
Listener: cl.Net.Listener,
@@ -166,8 +174,8 @@ func main() {
}
// parseArgs 加载配置文件、解析命令行覆盖项,并展开 Meshtastic channel PSK。
func parseArgs() (*config, error) {
cfg, err := loadConfig(defaultConfigPath())
func parseArgs() (*configpkg.Config, error) {
cfg, err := configpkg.Load(configpkg.DefaultPath())
if err != nil {
return nil, err
}
@@ -198,9 +206,9 @@ func parseArgs() (*config, error) {
if value := os.Getenv("MESH_ADMIN_SESSION_SECRET"); value != "" {
cfg.Web.Admin.SessionSecret = value
}
clearWebSocketPathOnUnsupportedGOOS(cfg, runtime.GOOS)
configpkg.ClearWebSocketPathOnUnsupportedGOOS(cfg, runtime.GOOS)
if err := validateConfig(cfg); err != nil {
if err := configpkg.Validate(cfg); err != nil {
return nil, err
}
key, err := mqtpp.ExpandPSK(cfg.Meshtastic.PSK)
@@ -212,38 +220,38 @@ func parseArgs() (*config, error) {
}
// run 创建 MQTT broker 和 Web 服务,并阻塞等待退出信号。
func run(cfg *config) error {
store, err := openStore(cfg.Database)
func run(cfg *configpkg.Config) error {
store, err := storepkg.OpenStore(cfg.Database)
if err != nil {
return err
}
defer store.Close()
dbQueue := newDBWriteQueue(store)
dbQueue := storepkg.NewWriteQueue(store)
defer dbQueue.Close()
if err := store.EnsureDefaultAdmin(cfg.Web.Admin.Username, cfg.Web.Admin.Password); err != nil {
return err
}
blocking, err := newBlockingCache(store)
blocking, err := blockingpkg.New(store)
if err != nil {
return err
}
settings, err := newRuntimeSettingsCache(store)
settings, err := rspkg.New(store)
if err != nil {
return err
}
messageStats := &meshtasticMessageStats{}
messageStats := &mqttforwardpkg.Stats{}
server, mqttHook, mqttAddr, err := startMQTTServer(cfg, store, dbQueue, messageStats, blocking, settings)
if err != nil {
return err
}
botSender := newBotService(store, server, cfg.Key)
botSender := botpkg.NewService(store, server, cfg.Key)
mqttHook.autoAcker = botSender.MaybeAutoAck
botCtx, stopBotBroadcaster := context.WithCancel(context.Background())
defer stopBotBroadcaster()
botSender.StartNodeInfoBroadcaster(botCtx)
forwardManager := newMQTTForwardManager(store)
forwardManager := mqttforwardpkg.NewManager(store)
if err := forwardManager.StartFromStore(); err != nil {
server.Close()
return err
@@ -262,12 +270,12 @@ func run(cfg *config) error {
providerConfigs := make([]llm.ProviderConfig, 0, len(llmProviders))
for _, p := range llmProviders {
providerConfigs = append(providerConfigs, llm.ProviderConfig{
Name: p.Name,
Active: p.Active,
APIKey: p.APIKey,
BaseURL: p.BaseURL,
Model: p.Model,
Timeout: p.Timeout,
Name: p.Name,
Active: p.Active,
APIKey: p.APIKey,
BaseURL: p.BaseURL,
Model: p.Model,
Timeout: p.Timeout,
ContextWindowTokens: p.ContextWindowTokens,
})
}
@@ -276,7 +284,7 @@ func run(cfg *config) error {
botSenderAdapter := autoreply.NewBotServiceAdapter(
// SendDirectText: 发送私聊消息
func(ctx context.Context, botID uint64, toNodeNum int64, text string) error {
_, err := botSender.SendText(ctx, botSendTextRequest{
_, err := botSender.SendText(ctx, botpkg.SendTextRequest{
BotID: botID,
MessageType: "direct",
ToNodeNum: &toNodeNum,
@@ -286,7 +294,7 @@ func run(cfg *config) error {
},
// SendChannelText: 发送频道消息
func(ctx context.Context, botID uint64, channelID string, text string) error {
_, err := botSender.SendText(ctx, botSendTextRequest{
_, err := botSender.SendText(ctx, botpkg.SendTextRequest{
BotID: botID,
MessageType: "channel",
ChannelID: channelID,
@@ -297,10 +305,10 @@ func run(cfg *config) error {
)
aiService, err = ai.NewService(ai.Config{
LLMProviders: providerConfigs,
DataDir: cfg.DataDir,
Enabled: cfg.AI.Enabled,
ToolConfigStore: store,
LLMProviders: providerConfigs,
DataDir: cfg.DataDir,
Enabled: cfg.AI.Enabled,
ToolConfigStore: store,
}, store.DB(), botSenderAdapter)
if err != nil {
fmt.Fprintf(os.Stderr, "Warning: failed to initialize AI service: %v\n", err)
@@ -319,12 +327,12 @@ func run(cfg *config) error {
var httpServers []*http.Server
errCh := make(chan error, 2)
if cfg.Web.Enabled {
sessions, err := newSessionManager(cfg.Web.Admin)
sessions, err := auth.NewManager(cfg.Web.Admin)
if err != nil {
return err
}
mqttStatus := mqttRuntimeStatus{server: server, address: mqttAddr, tls: cfg.MQTT.TLS.Enabled, stats: messageStats, dbQueue: dbQueue}
handler := newRouter(cfg.Web, store, sessions, mqttStatus, blocking, forwardManager, settings, botSender)
mqttStatus := webpkg.MQTTRuntimeStatus{Server: server, Address: mqttAddr, TLS: cfg.MQTT.TLS.Enabled, Stats: messageStats, DBQueue: dbQueue}
handler := webpkg.NewRouter(cfg.Web, store, sessions, mqttStatus, blocking, forwardManager, settings, botSender)
webAddresses := []string{}
if cfg.Web.PortEnabled {
httpServer := &http.Server{
@@ -344,7 +352,7 @@ func run(cfg *config) error {
httpServers = append(httpServers, httpServer)
webAddresses = append(webAddresses, cfg.Web.SocketPath)
go func() {
if err := serveHTTPUnixSocket(httpServer, cfg.Web.SocketPath); err != nil && !errors.Is(err, http.ErrServerClosed) {
if err := webpkg.ServeUnixSocket(httpServer, cfg.Web.SocketPath); err != nil && !errors.Is(err, http.ErrServerClosed) {
errCh <- err
}
}()
@@ -378,9 +386,9 @@ func run(cfg *config) error {
return runErr
}
func startMQTTServer(cfg *config, store *store, dbQueue *dbWriteQueue, stats *meshtasticMessageStats, blocking *blockingCache, settings *runtimeSettingsCache) (*mqtt.Server, *meshtasticFilterHook, string, error) {
func startMQTTServer(cfg *configpkg.Config, store *storepkg.Store, dbQueue *storepkg.WriteQueue, stats *mqttforwardpkg.Stats, blocking *blockingpkg.Cache, settings *rspkg.Cache) (*mqtt.Server, *meshtasticFilterHook, string, error) {
server := mqtt.New(&mqtt.Options{InlineClient: true})
if err := server.AddHook(new(auth.AllowHook), nil); err != nil {
if err := server.AddHook(new(mqttauth.AllowHook), nil); err != nil {
return nil, nil, "", err
}
hook := &meshtasticFilterHook{
@@ -389,14 +397,14 @@ func startMQTTServer(cfg *config, store *store, dbQueue *dbWriteQueue, stats *me
stats: stats,
blocking: blocking,
settings: settings,
pkiResolver: newPKIKeyResolver(store),
pkiResolver: botpkg.NewPKIKeyResolver(store),
}
if err := server.AddHook(hook, nil); err != nil {
return nil, nil, "", err
}
addr := net.JoinHostPort(cfg.MQTT.Host, strconv.Itoa(cfg.MQTT.Port))
tlsConfig, err := buildTLSConfig(cfg.MQTT.TLS)
tlsConfig, err := configpkg.BuildTLS(cfg.MQTT.TLS)
if err != nil {
return nil, nil, "", err
}
+16 -13
View File
@@ -4,11 +4,15 @@ import (
"testing"
mqtt "github.com/mochi-mqtt/server/v2"
blockingpkg "meshtastic_mqtt_server/internal/blocking"
storepkg "meshtastic_mqtt_server/internal/store"
"meshtastic_mqtt_server/internal/store/testutil"
)
func TestMQTTClientInfoFromClientNil(t *testing.T) {
info := mqttClientInfoFromClient(nil)
if info != (mqttClientInfo{}) {
if info != (storepkg.MQTTClientInfo{}) {
t.Fatalf("info = %#v, want zero value", info)
}
}
@@ -42,20 +46,19 @@ func TestMQTTClientInfoFromClientUnsplitRemote(t *testing.T) {
}
}
// 注:blockingViolationForRecord 的测试现在跟着 blockingCache 一起搬到了
// internal/blocking/violations_test.go,使用真实 *Store 构造缓存而不是
// 直接捏造未导出字段。这里保留 mqtt client info 这部分测试不动。
// blockingViolationForRecord 的测试用真实 *Store + blocking.Cache 走完整路径,
// 不依赖 cache 的未导出字段。
func TestBlockingViolationForRecordNode(t *testing.T) {
st := openTestStore(t)
st := testutil.OpenStore(t)
defer st.Close()
nodeNum := int64(305419896)
if _, err := st.CreateNodeBlocking("!12345678", &nodeNum, "blocked", true); err != nil {
t.Fatalf("CreateNodeBlocking() error = %v", err)
}
cache, err := newBlockingCache(st)
cache, err := blockingpkg.New(st)
if err != nil {
t.Fatalf("newBlockingCache() error = %v", err)
t.Fatalf("blocking.New() error = %v", err)
}
record := map[string]any{"type": "position", "from": "!12345678", "from_num": uint32(305419896)}
violation := blockingViolationForRecord(cache, record)
@@ -65,14 +68,14 @@ func TestBlockingViolationForRecordNode(t *testing.T) {
}
func TestBlockingViolationForRecordForbiddenWordFields(t *testing.T) {
st := openTestStore(t)
st := testutil.OpenStore(t)
defer st.Close()
if _, err := st.CreateForbiddenWordBlocking("spam", "contains", false, "blocked", true); err != nil {
t.Fatalf("CreateForbiddenWordBlocking() error = %v", err)
}
cache, err := newBlockingCache(st)
cache, err := blockingpkg.New(st)
if err != nil {
t.Fatalf("newBlockingCache() error = %v", err)
t.Fatalf("blocking.New() error = %v", err)
}
for _, tc := range []struct {
@@ -94,14 +97,14 @@ func TestBlockingViolationForRecordForbiddenWordFields(t *testing.T) {
}
func TestBlockingViolationForRecordAllowed(t *testing.T) {
st := openTestStore(t)
st := testutil.OpenStore(t)
defer st.Close()
if _, err := st.CreateForbiddenWordBlocking("spam", "contains", false, "blocked", true); err != nil {
t.Fatalf("CreateForbiddenWordBlocking() error = %v", err)
}
cache, err := newBlockingCache(st)
cache, err := blockingpkg.New(st)
if err != nil {
t.Fatalf("newBlockingCache() error = %v", err)
t.Fatalf("blocking.New() error = %v", err)
}
record := map[string]any{"type": "text_message", "from": "!1", "text": "hello"}
if violation := blockingViolationForRecord(cache, record); violation != nil {
-13
View File
@@ -1,13 +0,0 @@
package main
// 桥接到 internal/mapsource — 让 web.go 中的 registerMapSourceRoutes /
// registerAdminMapSourceRoutes 旧名字仍可用。
import (
"github.com/gin-gonic/gin"
mspkg "meshtastic_mqtt_server/internal/mapsource"
)
func registerMapSourceRoutes(r gin.IRouter, s *store) { mspkg.RegisterPublicRoutes(r, s) }
func registerAdminMapSourceRoutes(r gin.IRouter, s *store) { mspkg.RegisterAdminRoutes(r, s) }
-26
View File
@@ -1,26 +0,0 @@
package main
// 桥接到 internal/mqttforward — 让 main.go / web.go / mqtt_status.go 中
// 使用 mqttForwardManager / meshtasticMessageStats / mqttForwardReloader 等
// 旧名字的代码仍可工作。
import (
"github.com/gin-gonic/gin"
mfpkg "meshtastic_mqtt_server/internal/mqttforward"
)
type (
mqttForwardManager = mfpkg.Manager
mqttForwardReloader = mfpkg.Reloader
mqttForwardRuntimeStatus = mfpkg.RuntimeStatus
meshtasticMessageStats = mfpkg.Stats
)
func newMQTTForwardManager(s *store) *mqttForwardManager {
return mfpkg.NewManager(s)
}
func registerAdminMQTTForwardRoutes(r gin.IRouter, s *store, forwarder mqttForwardReloader) {
mfpkg.RegisterRoutes(r, s, forwarder)
}
-19
View File
@@ -1,19 +0,0 @@
package main
// 桥接到 internal/runtimesettings — 让根目录代码继续使用旧的小写名字。
import (
"github.com/gin-gonic/gin"
rspkg "meshtastic_mqtt_server/internal/runtimesettings"
)
type runtimeSettingsCache = rspkg.Cache
func newRuntimeSettingsCache(s *store) (*runtimeSettingsCache, error) {
return rspkg.New(s)
}
func registerAdminRuntimeSettingsRoutes(r gin.IRouter, s *store, c *runtimeSettingsCache) {
rspkg.RegisterRoutes(r, s, c)
}
-17
View File
@@ -1,17 +0,0 @@
package main
// 桥接到 internal/sign — 让 web.go 中 registerAdminSignRoutes / signDTO /
// signDayCountDTO 旧名字仍可用。
import (
"github.com/gin-gonic/gin"
signpkg "meshtastic_mqtt_server/internal/sign"
)
func registerAdminSignRoutes(r gin.IRouter, s *store) {
signpkg.RegisterAdminRoutes(r, s)
}
func signDTO(row signRecord) gin.H { return signpkg.SignDTO(row) }
func signDayCountDTO(row signDayCount) gin.H { return signpkg.SignDayCountDTO(row) }
-145
View File
@@ -1,145 +0,0 @@
package main
// 桥接到 internal/store —— 让根目录其余文件无须修改即可继续使用旧的小写类型/函数名。
// 当各领域包逐步迁出根目录后,可以删除这些别名。
import (
storepkg "meshtastic_mqtt_server/internal/store"
)
// ---- 类型别名 ----
type (
store = storepkg.Store
mqttClientInfo = storepkg.MQTTClientInfo
dbWriteQueue = storepkg.WriteQueue
listOptions = storepkg.ListOptions
mapReportViewportOptions = storepkg.MapReportViewportOptions
mapReportViewportResult = storepkg.MapReportViewportResult
mapReportClusterRecord = storepkg.MapReportClusterRecord
userRecord = storepkg.UserRecord
loginLogRecord = storepkg.LoginLogRecord
helpContentRecord = storepkg.HelpContentRecord
runtimeSettingRecord = storepkg.RuntimeSettingRecord
mapTileSourceRecord = storepkg.MapTileSourceRecord
mapTileSourceInput = storepkg.MapTileSourceInput
discardDetailsRecord = storepkg.DiscardDetailsRecord
signRecord = storepkg.SignRecord
nodeBlockingRecord = storepkg.NodeBlockingRecord
ipBlockingRecord = storepkg.IPBlockingRecord
forbiddenWordBlockingRecord = storepkg.ForbiddenWordBlockingRecord
mqttForwarderRecord = storepkg.MQTTForwarderRecord
mqttForwarderInput = storepkg.MQTTForwarderInput
mqttForwardTopicRecord = storepkg.MQTTForwardTopicRecord
mqttForwardTopicInput = storepkg.MQTTForwardTopicInput
botNodeRecord = storepkg.BotNodeRecord
botNodeInput = storepkg.BotNodeInput
botMessageRecord = storepkg.BotMessageRecord
botDirectMessageRecord = storepkg.BotDirectMessageRecord
llmMessageQueueRecord = storepkg.LLMMessageQueueRecord
nodeInfoRecord = storepkg.NodeInfoRecord
mapReportRecord = storepkg.MapReportRecord
textMessageRecord = storepkg.TextMessageRecord
llmProviderRecord = storepkg.LLMProviderRecord
llmToolRouterRecord = storepkg.LLMToolRouterRecord
llmPrimaryConfigRecord = storepkg.LLMPrimaryConfigRecord
positionRecord = storepkg.PositionRecord
telemetryRecord = storepkg.TelemetryRecord
routingRecord = storepkg.RoutingRecord
tracerouteRecord = storepkg.TracerouteRecord
)
// AppendPacketFields / MQTTClientRecordFields 已经是导出名,不需要别名。
// 直接用包限定名供 root 文件调用:
type (
AppendPacketFields = storepkg.AppendPacketFields
MQTTClientRecordFields = storepkg.MQTTClientRecordFields
)
// 其它额外导出类型的别名(旧的小写形式仍被根目录文件直接使用)。
type (
runtimeSettingsSnapshot = storepkg.RuntimeSettingsSnapshot
mqttForwarderConfig = storepkg.MQTTForwarderConfig
botDirectMessageListOptions = storepkg.BotDirectMessageListOptions
botMessageListOptions = storepkg.BotMessageListOptions
botDirectConversation = storepkg.BotDirectConversation
signDayCount = storepkg.SignDayCount
)
var errBlockingAlreadyExists = storepkg.ErrBlockingAlreadyExists
var errBotNodeAlreadyExists = storepkg.ErrBotNodeAlreadyExists
var (
errMapTileSourceAlreadyExists = storepkg.ErrMapTileSourceAlreadyExists
errMapTileSourceCannotDeleteDefault = storepkg.ErrMapTileSourceCannotDeleteDefault
errMapTileSourceCannotDisableDefault = storepkg.ErrMapTileSourceCannotDisableDefault
errMapTileSourceDefaultMustBeEnabled = storepkg.ErrMapTileSourceDefaultMustBeEnabled
)
func mapTileSourceHash(urlTemplate string) string {
return storepkg.MapTileSourceHash(urlTemplate)
}
const (
forbiddenWordMatchContains = storepkg.ForbiddenWordMatchContains
runtimeSettingAllowEncryptedForwarding = storepkg.RuntimeSettingAllowEncryptedForwarding
runtimeSettingLLMQueueEnabled = storepkg.RuntimeSettingLLMQueueEnabled
runtimeSettingLLMQueueIncludeChannel = storepkg.RuntimeSettingLLMQueueIncludeChannel
botDefaultPSK = storepkg.BotDefaultPSK
botMessageTypeChannel = storepkg.BotMessageTypeChannel
botMessageTypeDirect = storepkg.BotMessageTypeDirect
botMessageStatusPending = storepkg.BotMessageStatusPending
botMessageStatusPublished = storepkg.BotMessageStatusPublished
botMessageStatusFailed = storepkg.BotMessageStatusFailed
botDirectMessageDirectionInbound = storepkg.BotDirectMessageDirectionInbound
botDirectMessageDirectionOutbound = storepkg.BotDirectMessageDirectionOutbound
botDefaultTopicPrefix = storepkg.BotDefaultTopicPrefix
mqttForwardDirectionSourceToTarget = storepkg.MQTTForwardDirectionSourceToTarget
mqttForwardDirectionBidirectional = storepkg.MQTTForwardDirectionBidirectional
)
const botDefaultNodeInfoBroadcastSeconds = storepkg.BotDefaultNodeInfoBroadcastSeconds
func validateBotNodeNum(n int64) error { return storepkg.ValidateBotNodeNum(n) }
var errUserAlreadyExists = storepkg.ErrUserAlreadyExists
var (
errMQTTForwarderAlreadyExists = storepkg.ErrMQTTForwarderAlreadyExists
errMQTTForwardTopicAlreadyExists = storepkg.ErrMQTTForwardTopicAlreadyExists
)
func nullableString(v any) *string { return storepkg.NullableString(v) }
func nullableStringValue(v any) *string { return storepkg.NullableStringValue(v) }
func decodeBotPublicKey(row botNodeRecord) ([]byte, error) {
return storepkg.DecodeBotPublicKey(row)
}
// LLM 消息队列状态字符串常量。
const (
llmMessageStatusPending = storepkg.LLMMessageStatusPending
llmMessageStatusProcessing = storepkg.LLMMessageStatusProcessing
llmMessageStatusProcessed = storepkg.LLMMessageStatusProcessed
llmMessageStatusError = storepkg.LLMMessageStatusError
)
const defaultHelpMarkdown = storepkg.DefaultHelpMarkdown
// 旧名 llmMessageDTO 现在通过 store 提供。
func llmMessageDTO(row llmMessageQueueRecord) map[string]any {
return storepkg.LLMMessageDTO(row)
}
// ---- 工厂函数包装 ----
func openStore(cfg databaseConfig) (*store, error) { return storepkg.OpenStore(cfg) }
func normalizeListOptions(o listOptions) listOptions {
return storepkg.NormalizeListOptions(o)
}
func normalizeMapReportViewportOptions(o mapReportViewportOptions) mapReportViewportOptions {
return storepkg.NormalizeMapReportViewportOptions(o)
}
// newDBWriteQueue 在新包里更名,提供旧名字避免改 main.go。
func newDBWriteQueue(s *store) *dbWriteQueue { return storepkg.NewWriteQueue(s) }
-21
View File
@@ -1,21 +0,0 @@
package main
import (
"path/filepath"
"testing"
storepkg "meshtastic_mqtt_server/internal/store"
)
// openTestStore 在根目录的测试中沿用旧函数名,但底层调用 internal/store 的实现。
func openTestStore(t *testing.T) *store {
t.Helper()
st, err := storepkg.OpenStore(databaseConfig{
Driver: databaseDriverSQLite,
SQLite: sqliteConfig{Path: filepath.Join(t.TempDir(), "mesh_mqtt_go.db")},
})
if err != nil {
t.Fatalf("OpenStore() error = %v", err)
}
return st
}
-56
View File
@@ -1,56 +0,0 @@
package main
// 桥接到 internal/web — 让 main.go 中使用 newSessionManager / newRouter /
// mqttRuntimeStatus / serveHTTPUnixSocket 这些旧名字的代码继续编译。
import (
"net/http"
"github.com/gin-gonic/gin"
mqtt "github.com/mochi-mqtt/server/v2"
"meshtastic_mqtt_server/internal/auth"
mqttforwardpkg "meshtastic_mqtt_server/internal/mqttforward"
storepkg "meshtastic_mqtt_server/internal/store"
webpkg "meshtastic_mqtt_server/internal/web"
)
// 旧类型/旧函数名 → 新位置的别名。
type mqttRuntimeStatusInternal = webpkg.MQTTRuntimeStatus
// mqttRuntimeStatus 旧名字保持小写、字段也是小写——这里用一个适配类型把
// main 包的旧字段写法包到 web 包导出的大写字段上。
type mqttRuntimeStatus struct {
server *mqtt.Server
address string
tls bool
stats *meshtasticMessageStats
dbQueue *dbWriteQueue
}
// 让 mqttRuntimeStatus 自动实现 webpkg.MQTTStatusProvider,把请求转给真正的实现。
func (m mqttRuntimeStatus) Status() webpkg.AdminMQTTStatus {
return webpkg.MQTTRuntimeStatus{
Server: m.server,
Address: m.address,
TLS: m.tls,
Stats: m.stats,
DBQueue: m.dbQueue,
}.Status()
}
// 让旧代码里 `mqttforwardpkg.Stats` 别名留作 main 包内可见。
var _ *mqttforwardpkg.Stats = (*meshtasticMessageStats)(nil)
func newSessionManager(cfg webAdminConfig) (*auth.Manager, error) {
return auth.NewManager(cfg)
}
func newRouter(cfg webConfig, store *storepkg.Store, sessions *auth.Manager, mqttStatus webpkg.MQTTStatusProvider, blocking *blockingCache, forwarder mqttForwardReloader, settings *runtimeSettingsCache, botSender botTextSender) *gin.Engine {
return webpkg.NewRouter(cfg, store, sessions, mqttStatus, blocking, forwarder, settings, botSender)
}
func serveHTTPUnixSocket(server *http.Server, socketPath string) error {
return webpkg.ServeUnixSocket(server, socketPath)
}