Files
CLIProxyAPI/sdk/cliproxy/builder.go
2025-09-22 01:40:24 +08:00

139 lines
4.0 KiB
Go

package cliproxy
import (
"fmt"
"github.com/router-for-me/CLIProxyAPI/v6/internal/api"
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
sdkAuth "github.com/router-for-me/CLIProxyAPI/v6/sdk/auth"
coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
)
// Builder constructs a Service instance with customizable providers.
type Builder struct {
cfg *config.Config
configPath string
tokenProvider TokenClientProvider
apiKeyProvider APIKeyClientProvider
watcherFactory WatcherFactory
hooks Hooks
authManager *sdkAuth.Manager
coreManager *coreauth.Manager
serverOptions []api.ServerOption
}
// Hooks allows callers to plug into service lifecycle stages.
type Hooks struct {
OnBeforeStart func(*config.Config)
OnAfterStart func(*Service)
}
// NewBuilder creates a Builder with default dependencies left unset.
func NewBuilder() *Builder {
return &Builder{}
}
// WithConfig sets the configuration instance used by the service.
func (b *Builder) WithConfig(cfg *config.Config) *Builder {
b.cfg = cfg
return b
}
// WithConfigPath sets the absolute configuration file path used for reload watching.
func (b *Builder) WithConfigPath(path string) *Builder {
b.configPath = path
return b
}
// WithTokenClientProvider overrides the provider responsible for token-backed clients.
func (b *Builder) WithTokenClientProvider(provider TokenClientProvider) *Builder {
b.tokenProvider = provider
return b
}
// WithAPIKeyClientProvider overrides the provider responsible for API key-backed clients.
func (b *Builder) WithAPIKeyClientProvider(provider APIKeyClientProvider) *Builder {
b.apiKeyProvider = provider
return b
}
// WithWatcherFactory allows customizing the watcher factory that handles reloads.
func (b *Builder) WithWatcherFactory(factory WatcherFactory) *Builder {
b.watcherFactory = factory
return b
}
// WithHooks registers lifecycle hooks executed around service startup.
func (b *Builder) WithHooks(h Hooks) *Builder {
b.hooks = h
return b
}
// WithAuthManager overrides the authentication manager used for token lifecycle operations.
func (b *Builder) WithAuthManager(mgr *sdkAuth.Manager) *Builder {
b.authManager = mgr
return b
}
// WithCoreAuthManager overrides the runtime auth manager responsible for request execution.
func (b *Builder) WithCoreAuthManager(mgr *coreauth.Manager) *Builder {
b.coreManager = mgr
return b
}
// WithServerOptions appends server configuration options used during construction.
func (b *Builder) WithServerOptions(opts ...api.ServerOption) *Builder {
b.serverOptions = append(b.serverOptions, opts...)
return b
}
// Build validates inputs, applies defaults, and returns a ready-to-run service.
func (b *Builder) Build() (*Service, error) {
if b.cfg == nil {
return nil, fmt.Errorf("cliproxy: configuration is required")
}
if b.configPath == "" {
return nil, fmt.Errorf("cliproxy: configuration path is required")
}
tokenProvider := b.tokenProvider
if tokenProvider == nil {
tokenProvider = NewFileTokenClientProvider()
}
apiKeyProvider := b.apiKeyProvider
if apiKeyProvider == nil {
apiKeyProvider = NewAPIKeyClientProvider()
}
watcherFactory := b.watcherFactory
if watcherFactory == nil {
watcherFactory = defaultWatcherFactory
}
authManager := b.authManager
if authManager == nil {
authManager = newDefaultAuthManager()
}
coreManager := b.coreManager
if coreManager == nil {
coreManager = coreauth.NewManager(coreauth.NewFileStore(b.cfg.AuthDir), nil, nil)
}
// Attach a default RoundTripper provider so providers can opt-in per-auth transports.
coreManager.SetRoundTripperProvider(newDefaultRoundTripperProvider())
service := &Service{
cfg: b.cfg,
configPath: b.configPath,
tokenProvider: tokenProvider,
apiKeyProvider: apiKeyProvider,
watcherFactory: watcherFactory,
hooks: b.hooks,
authManager: authManager,
coreManager: coreManager,
serverOptions: append([]api.ServerOption(nil), b.serverOptions...),
}
return service, nil
}