modular

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2025 License: MIT Imports: 10 Imported by: 17

README

modular

Modular Go

Go Reference CodeQL Dependabot Updates CI

Overview

Modular is a package that provides a structured way to create modular applications in Go. It allows you to build applications as collections of modules that can be easily added, removed, or replaced. Key features include:

  • Module lifecycle management: Initialize, start, and gracefully stop modules
  • Dependency management: Automatically resolve and order module dependencies
  • Service registry: Register and retrieve application services
  • Configuration management: Handle configuration for modules and services
  • Dependency injection: Inject required services into modules

Installation

go get github.com/GoCodeAlone/modular

Usage

Basic Application
package main

import (
    "github.com/GoCodeAlone/modular"
    "log/slog"
    "os"
)

func main() {
    // Create a logger
    logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
    
    // Create config provider with application configuration
    config := &AppConfig{
        Name: "MyApp",
        Version: "1.0.0",
    }
    configProvider := modular.NewStdConfigProvider(config)
    
    // Create the application
    app := modular.NewApplication(configProvider, logger)
    
    // Register modules
    app.RegisterModule(NewDatabaseModule())
    app.RegisterModule(NewAPIModule())
    
    // Run the application (this will block until the application is terminated)
    if err := app.Run(); err != nil {
        logger.Error("Application error", "error", err)
        os.Exit(1)
    }
}
Creating a Module
type DatabaseModule struct {
    db     *sql.DB
    config *DatabaseConfig
}

func NewDatabaseModule() modular.Module {
    return &DatabaseModule{}
}

// RegisterConfig registers the module's configuration
func (m *DatabaseModule) RegisterConfig(app *modular.Application) {
    m.config = &DatabaseConfig{
        DSN: "postgres://user:password@localhost:5432/dbname",
    }
    app.RegisterConfigSection("database", modular.NewStdConfigProvider(m.config))
}

// Name returns the module's unique name
func (m *DatabaseModule) Name() string {
    return "database"
}

// Dependencies returns other modules this module depends on
func (m *DatabaseModule) Dependencies() []string {
    return []string{} // No dependencies
}

// Init initializes the module
func (m *DatabaseModule) Init(app *modular.Application) error {
    // Initialize database connection
    db, err := sql.Open("postgres", m.config.DSN)
    if err != nil {
        return err
    }
    m.db = db
    return nil
}

// ProvidesServices returns services provided by this module
func (m *DatabaseModule) ProvidesServices() []modular.ServiceProvider {
    return []modular.ServiceProvider{
        {
            Name:        "database",
            Description: "Database connection",
            Instance:    m.db,
        },
    }
}

// RequiresServices returns services required by this module
func (m *DatabaseModule) RequiresServices() []modular.ServiceDependency {
    return []modular.ServiceDependency{} // No required services
}

// Start starts the module
func (m *DatabaseModule) Start(ctx context.Context) error {
    return nil // Database is already connected
}

// Stop stops the module
func (m *DatabaseModule) Stop(ctx context.Context) error {
    return m.db.Close()
}
Service Dependencies
// A module that depends on another service
func (m *APIModule) RequiresServices() []modular.ServiceDependency {
    return []modular.ServiceDependency{
        {
            Name:     "database",
            Required: true,  // Application won't start if this service is missing
        },
        {
            Name:     "cache",
            Required: false, // Optional dependency
        },
    }
}

// Using constructor injection
func (m *APIModule) Constructor() modular.ModuleConstructor {
    return func(app *modular.Application, services map[string]any) (modular.Module, error) {
        // Services that were requested in RequiresServices() are available here
        db := services["database"].(*sql.DB)
        
        // Create a new module instance with injected services
        return &APIModule{
            db: db,
        }, nil
    }
}
Configuration Management
// Define your configuration struct
type AppConfig struct {
    Name    string `json:"name" yaml:"name"`
    Version string `json:"version" yaml:"version"`
}

// Implement ConfigSetup interface if needed
func (c *AppConfig) Setup() error {
    // Validate configuration or set defaults
    if c.Name == "" {
        c.Name = "DefaultApp"
    }
    return nil
}

Key Interfaces

Module

The core interface that all modules must implement:

type Module interface {
    RegisterConfig(app *Application)
    Init(app *Application) error
    Start(ctx context.Context) error
    Stop(ctx context.Context) error
    Name() string
    Dependencies() []string
    ProvidesServices() []ServiceProvider
    RequiresServices() []ServiceDependency
}
ConfigProvider

Interface for configuration providers:

type ConfigProvider interface {
    GetConfig() any
}

License

MIT License

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ConfigFeeders = []Feeder{
	feeders.EnvFeeder{},
}

Functions

This section is empty.

Types

type AppRegistry

type AppRegistry interface {
	SvcRegistry() ServiceRegistry
}

type Application

type Application struct {
	// contains filtered or unexported fields
}

Application represents the core Application container

func NewApplication

func NewApplication(cp ConfigProvider, logger Logger) *Application

NewApplication creates a new application instance

func (*Application) ConfigProvider

func (app *Application) ConfigProvider() ConfigProvider

ConfigProvider retrieves the application config provider

func (*Application) GetConfigSection

func (app *Application) GetConfigSection(section string) (ConfigProvider, error)

GetConfigSection retrieves a configuration section

func (*Application) GetService

func (app *Application) GetService(name string, target any) error

GetService retrieves a service with type assertion

func (*Application) Init

func (app *Application) Init() error

Init initializes the application with the provided modules

func (*Application) Logger

func (app *Application) Logger() Logger

Logger represents a logger

func (*Application) RegisterConfigSection

func (app *Application) RegisterConfigSection(section string, cp ConfigProvider)

RegisterConfigSection registers a configuration section with the application

func (*Application) RegisterModule

func (app *Application) RegisterModule(module Module)

RegisterModule adds a module to the application

func (*Application) RegisterService

func (app *Application) RegisterService(name string, service any) error

RegisterService adds a service with type checking

func (*Application) Run

func (app *Application) Run() error

Run starts the application and blocks until termination

func (*Application) Start

func (app *Application) Start() error

Start starts the application

func (*Application) Stop

func (app *Application) Stop() error

Stop stops the application

func (*Application) SvcRegistry

func (app *Application) SvcRegistry() ServiceRegistry

SvcRegistry retrieves the service svcRegistry

type ComplexFeeder

type ComplexFeeder interface {
	Feeder
	FeedKey(string, interface{}) error
}

type Config

type Config struct {
	*config.Config
	StructKeys map[string]interface{}
}

func NewConfig

func NewConfig() *Config

func (*Config) AddStructKey

func (c *Config) AddStructKey(key string, target interface{}) *Config

func (*Config) Feed

func (c *Config) Feed() error

type ConfigProvider

type ConfigProvider interface {
	GetConfig() any
}

type ConfigSetup added in v1.0.0

type ConfigSetup interface {
	Setup() error
}

ConfigSetup is an interface that configs can implement to perform additional setup after being populated by feeders

type Feeder

type Feeder = config.Feeder

Feeder aliases

type LoadAppConfigFunc added in v1.0.0

type LoadAppConfigFunc func(*Application) error

LoadAppConfigFunc is the function type for loading application configuration

var AppConfigLoader LoadAppConfigFunc = loadAppConfig

AppConfigLoader is the default implementation that can be replaced in tests

type Logger

type Logger interface {
	Info(msg string, args ...any)
	Error(msg string, args ...any)
	Warn(msg string, args ...any)
	Debug(msg string, args ...any)
}

type Module

type Module interface {
	// RegisterConfig registers configuration requirements
	RegisterConfig(app *Application)

	// Init Initialize the module with the application context
	Init(app *Application) error

	// Start starts the module (non-blocking)
	Start(ctx context.Context) error

	// Stop gracefully stops the module
	Stop(ctx context.Context) error

	// Name returns the unique identifier for this module
	Name() string

	// Dependencies returns names of other modules this module depends on
	Dependencies() []string

	// ProvidesServices returns a list of services provided by this module
	ProvidesServices() []ServiceProvider

	// RequiresServices returns a list of services required by this module
	RequiresServices() []ServiceDependency
}

Module represents a registrable component in the application

type ModuleConstructor

type ModuleConstructor func(app *Application, services map[string]any) (Module, error)

type ModuleRegistry

type ModuleRegistry map[string]Module

ModuleRegistry represents a svcRegistry of modules

type ModuleWithConstructor

type ModuleWithConstructor interface {
	Module
	Constructor() ModuleConstructor
}

type ServiceDependency

type ServiceDependency struct {
	Name               string
	Required           bool
	Type               reflect.Type // Concrete type (if known)
	SatisfiesInterface reflect.Type // Interface type (if known)
}

ServiceDependency defines a dependency on a service

type ServiceProvider added in v1.0.0

type ServiceProvider struct {
	Name        string
	Description string
	Instance    any
}

ServiceProvider defines a service with metadata

type ServiceRegistry

type ServiceRegistry map[string]any

ServiceRegistry allows registration and retrieval of services

type StdConfigProvider

type StdConfigProvider struct {
	// contains filtered or unexported fields
}

func NewStdConfigProvider

func NewStdConfigProvider(cfg any) *StdConfigProvider

func (*StdConfigProvider) GetConfig

func (s *StdConfigProvider) GetConfig() any

Directories

Path Synopsis
cmd
modcli module
modules
auth module
cache module
chimux module
database module
eventbus module
eventlogger module
httpclient module
httpserver module
jsonschema module
letsencrypt module
logmasker module
reverseproxy module
scheduler module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL