优化结构

This commit is contained in:
Yvan
2026-08-23 00:38:33 +08:00
parent 64459574b2
commit 4e5071ee65
22 changed files with 301 additions and 127 deletions
+24
View File
@@ -0,0 +1,24 @@
// Package modules owns the static declarations of built-in business modules.
// It is intentionally separate from app: modules describe what they provide,
// while app composes runtime objects that need constructed dependencies.
package modules
import (
integrationmodule "kra/internal/modules/integration"
paymentmodule "kra/internal/modules/payment"
systemmodule "kra/internal/modules/system"
taskmodule "kra/internal/modules/task"
"kra/pkg/module"
)
// Catalog returns the modules enabled in this binary in dependency order.
// Keep this as the single static registration point for migrations, admin
// metadata and dependency-free timed tasks.
func Catalog() module.Catalog {
return module.Catalog{Definitions: []module.Definition{
systemmodule.Definition(),
integrationmodule.Definition(),
taskmodule.Definition(),
paymentmodule.Definition(),
}}
}
+37
View File
@@ -0,0 +1,37 @@
package modules
import "testing"
func TestCatalogMigrationIDsAreUnique(t *testing.T) {
seen := map[string]string{}
for _, definition := range Catalog().Definitions {
for _, step := range definition.Migrations {
if previous, exists := seen[step.ID]; exists {
t.Fatalf("migration %q is declared by both %s and %s", step.ID, previous, definition.Name)
}
seen[step.ID] = definition.Name
}
}
}
func TestCatalogContainsBuiltInModulesInDependencyOrder(t *testing.T) {
catalog := Catalog()
if len(catalog.Definitions) != 4 {
t.Fatalf("definitions = %d, want 4", len(catalog.Definitions))
}
want := []string{"system", "integration", "task", "payment"}
for index, name := range want {
if got := catalog.Definitions[index].Name; got != name {
t.Fatalf("definition[%d] = %q, want %q", index, got, name)
}
}
if got := catalog.MigrationSteps(); len(got) != 8 {
t.Fatalf("module migrations = %d, want 8", len(got))
}
if surface := catalog.Surface(); len(surface.Menus) != 3 || len(surface.APIs) != 15 {
t.Fatalf("admin surface = %d menus/%d APIs, want 3/15", len(surface.Menus), len(surface.APIs))
}
if got := catalog.DefaultTimedTasks(); len(got) != 2 {
t.Fatalf("default timed tasks = %d, want 2", len(got))
}
}
@@ -4,7 +4,7 @@ import "testing"
func TestDefinitionOwnsCommunicationSurface(t *testing.T) {
definition := Definition()
if definition.Name != "integration" || len(definition.Surface.Menus) != 1 || len(definition.Surface.APIs) != 5 {
if definition.Name != "integration" || len(definition.Migrations) != 3 || len(definition.Surface.Menus) != 1 || len(definition.Surface.APIs) != 5 {
t.Fatalf("integration surface = %#v", definition.Surface)
}
}
+2 -2
View File
@@ -7,8 +7,8 @@ func TestDefinitionOwnsPaymentContributions(t *testing.T) {
if definition.Name != "payment" {
t.Fatalf("name = %q, want payment", definition.Name)
}
if len(definition.Migrations) != 2 {
t.Fatalf("migrations = %d, want 2", len(definition.Migrations))
if len(definition.Migrations) != 1 {
t.Fatalf("migrations = %d, want 1", len(definition.Migrations))
}
if len(definition.Surface.Menus) != 2 || len(definition.Surface.APIs) != 10 {
t.Fatalf("surface = %d menus/%d APIs, want 2/10", len(definition.Surface.Menus), len(definition.Surface.APIs))