module

package
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Apr 22, 2026 License: GPL-3.0 Imports: 19 Imported by: 0

Documentation

Overview

Package module provides a module system for extending oCMS functionality. Modules can register routes, admin routes, template functions, and hooks to integrate with the core application.

Index

Constants

View Source
const (
	// HookPageAfterSave is fired after a page is saved.
	HookPageAfterSave = "page.after_save"
	// HookPageBeforeRender is fired before a page is rendered.
	HookPageBeforeRender = "page.before_render"

	// HookSecurityHoneypotTriggered is fired when a form honeypot field is filled.
	// Data: map[string]any with keys "ip", "form_slug", "form_id", "request_url".
	HookSecurityHoneypotTriggered = "security.honeypot_triggered"
)

Predefined hook names for common events.

Variables

This section is empty.

Functions

func RegisterCustomModule added in v0.8.0

func RegisterCustomModule(m Module)

RegisterCustomModule registers a custom module for automatic loading. Call this from an init() function in your custom module package:

func init() { module.RegisterCustomModule(New()) }

The module will be registered with the main registry during startup.

Types

type BaseModule

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

BaseModule provides a default implementation of the Module interface. Modules can embed this struct to get default no-op implementations.

func NewBaseModule

func NewBaseModule(name, version, description string) BaseModule

NewBaseModule creates a new BaseModule with the given metadata.

func (*BaseModule) AdminURL

func (m *BaseModule) AdminURL() string

AdminURL returns the admin dashboard URL (empty by default).

func (*BaseModule) Context

func (m *BaseModule) Context() *Context

Context returns the module context (for use by embedded modules).

func (*BaseModule) Dependencies

func (m *BaseModule) Dependencies() []string

Dependencies returns the list of module dependencies (empty by default).

func (*BaseModule) Description

func (m *BaseModule) Description() string

Description returns the module description.

func (*BaseModule) Init

func (m *BaseModule) Init(ctx *Context) error

Init initializes the module with the given context.

func (*BaseModule) Migrations

func (m *BaseModule) Migrations() []Migration

Migrations returns module migrations (empty by default).

func (*BaseModule) Name

func (m *BaseModule) Name() string

Name returns the module name.

func (*BaseModule) RegisterAdminRoutes

func (m *BaseModule) RegisterAdminRoutes(_ chi.Router)

RegisterAdminRoutes registers admin routes (no-op by default).

func (*BaseModule) RegisterRoutes

func (m *BaseModule) RegisterRoutes(_ chi.Router)

RegisterRoutes registers public routes (no-op by default).

func (*BaseModule) Shutdown

func (m *BaseModule) Shutdown() error

Shutdown performs cleanup when the module is shutting down.

func (*BaseModule) SidebarLabel

func (m *BaseModule) SidebarLabel() string

SidebarLabel returns the sidebar display label (empty = use name).

func (*BaseModule) TemplateFuncs

func (m *BaseModule) TemplateFuncs() template.FuncMap

TemplateFuncs returns template functions (empty by default).

func (*BaseModule) TranslationsFS

func (m *BaseModule) TranslationsFS() embed.FS

TranslationsFS returns nil (no translations by default).

func (*BaseModule) Version

func (m *BaseModule) Version() string

Version returns the module version.

type Context

type Context struct {
	DB                *sql.DB
	Store             *store.Queries
	Logger            *slog.Logger
	Config            *config.Config
	Render            *render.Renderer
	Events            *service.EventService
	Hooks             *HookRegistry
	SchedulerRegistry *scheduler.Registry
}

Context provides access to application services for modules.

type EnvironmentChecker

type EnvironmentChecker interface {
	AllowedEnvs() []string
}

EnvironmentChecker is an optional interface modules can implement to restrict which environments they can run in. When a module is first registered in the database, if it implements this interface and the current environment is not in the allowed list, it will be inserted as inactive (is_active=0).

type HookFunc

type HookFunc func(ctx context.Context, data any) (any, error)

HookFunc is a function that can be registered as a hook handler. It receives a context and data, and returns modified data and an error. If the hook returns an error, subsequent hooks are not called.

type HookHandler

type HookHandler struct {
	Name     string   // Name of the handler for debugging
	Module   string   // Module that registered the handler
	Priority int      // Lower priority runs first (default: 0)
	Fn       HookFunc // The actual handler function
}

HookHandler wraps a HookFunc with metadata.

type HookHandlerInfo

type HookHandlerInfo struct {
	Name     string
	Module   string
	Priority int
}

HookHandlerInfo contains information about a hook handler.

type HookInfo

type HookInfo struct {
	Name     string
	Handlers []HookHandlerInfo
}

HookInfo contains information about a registered hook.

type HookRegistry

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

HookRegistry manages hook registration and execution.

func NewHookRegistry

func NewHookRegistry(logger *slog.Logger) *HookRegistry

NewHookRegistry creates a new hook registry.

func (*HookRegistry) Call

func (h *HookRegistry) Call(ctx context.Context, hookName string, data any) (any, error)

Call executes all handlers for the given hook name. Handlers are executed in priority order (lower first). Handlers from inactive modules are skipped. The data is passed through each handler, allowing modification. If any handler returns an error, execution stops and the error is returned.

func (*HookRegistry) CallNoResult

func (h *HookRegistry) CallNoResult(ctx context.Context, hookName string, data any) error

CallNoResult executes hooks without expecting a modified result. This is useful for "after" hooks that just need to be notified.

func (*HookRegistry) Clear

func (h *HookRegistry) Clear()

Clear removes all registered hooks.

func (*HookRegistry) HandlerCount

func (h *HookRegistry) HandlerCount(hookName string) int

HandlerCount returns the number of handlers registered for a hook.

func (*HookRegistry) HasActiveHandlers added in v0.18.1

func (h *HookRegistry) HasActiveHandlers(hookName string) bool

HasActiveHandlers returns true if there are active handlers for the hook.

func (*HookRegistry) HasHandlers

func (h *HookRegistry) HasHandlers(hookName string) bool

HasHandlers returns true if there are handlers registered for the hook.

func (*HookRegistry) ListHookInfo

func (h *HookRegistry) ListHookInfo() []HookInfo

ListHookInfo returns detailed information about all registered hooks, sorted by name.

func (*HookRegistry) ListHooks

func (h *HookRegistry) ListHooks() []string

ListHooks returns all registered hook names, sorted alphabetically.

func (*HookRegistry) Register

func (h *HookRegistry) Register(hookName string, handler HookHandler)

Register adds a hook handler for the given hook name.

func (*HookRegistry) RegisterFunc

func (h *HookRegistry) RegisterFunc(hookName, handlerName, moduleName string, fn HookFunc)

RegisterFunc is a convenience method to register a simple hook function.

func (*HookRegistry) SetIsModuleActive

func (h *HookRegistry) SetIsModuleActive(fn IsModuleActiveFunc)

SetIsModuleActive sets the callback function to check if a module is active.

func (*HookRegistry) Unregister

func (h *HookRegistry) Unregister(hookName, moduleName string)

Unregister removes all handlers for a hook from a specific module.

func (*HookRegistry) UnregisterAll

func (h *HookRegistry) UnregisterAll(moduleName string)

UnregisterAll removes all handlers registered by a module.

type Info

type Info struct {
	Name              string
	Version           string
	Description       string
	Initialized       bool
	Active            bool   // Whether the module is active (routes/hooks enabled)
	ShowInSidebar     bool   // Whether the module appears in admin sidebar
	MigrationCount    int    // Total number of migrations defined
	MigrationsApplied int    // Number of migrations applied
	MigrationsPending int    // Number of pending migrations
	HasMigrations     bool   // Whether the module has any migrations
	AdminURL          string // URL to module's admin dashboard (empty if none)
}

Info contains information about a registered module.

type IsModuleActiveFunc

type IsModuleActiveFunc func(moduleName string) bool

IsModuleActiveFunc is a function that checks if a module is active.

type Migration

type Migration struct {
	Version     int64
	Description string
	Up          func(db *sql.DB) error
	Down        func(db *sql.DB) error
}

Migration represents a database migration for a module.

type MigrationInfo

type MigrationInfo struct {
	Version     int64
	Description string
	Applied     bool
}

MigrationInfo contains information about a module migration.

type Module

type Module interface {
	// Name returns the module name.
	Name() string
	// Version returns the module version.
	Version() string
	// Description returns the module description.
	Description() string
	// Dependencies returns the list of module dependencies.
	Dependencies() []string

	// Init initializes the module with the given context.
	Init(ctx *Context) error
	// Shutdown performs cleanup when the module is shutting down.
	Shutdown() error

	// RegisterRoutes registers public routes for the module.
	RegisterRoutes(r chi.Router)

	// RegisterAdminRoutes registers admin routes for the module.
	RegisterAdminRoutes(r chi.Router)

	// TemplateFuncs returns template functions provided by the module.
	TemplateFuncs() template.FuncMap

	// Migrations returns migrations for the module.
	Migrations() []Migration

	// AdminURL returns the admin dashboard URL for the module (e.g., "/admin/developer").
	// Return empty string if module has no admin dashboard.
	AdminURL() string

	// SidebarLabel returns the display label for the admin sidebar.
	// Return empty string to use the module name as label.
	SidebarLabel() string

	// TranslationsFS returns an embedded filesystem containing module translations.
	// Expected structure: locales/{lang}/messages.json
	// Return nil if module has no translations.
	TranslationsFS() embed.FS
}

Module defines the interface that all modules must implement.

func CustomModules added in v0.8.0

func CustomModules() []Module

CustomModules returns all custom modules registered via RegisterCustomModule.

type Registry

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

Registry manages module registration and lifecycle.

func NewRegistry

func NewRegistry(logger *slog.Logger) *Registry

NewRegistry creates a new module registry.

func (*Registry) AdminRouteAll

func (r *Registry) AdminRouteAll(router chi.Router)

AdminRouteAll registers all module admin routes with active status middleware.

func (*Registry) AllTemplateFuncs

func (r *Registry) AllTemplateFuncs() template.FuncMap

AllTemplateFuncs returns combined template functions from all active modules.

func (*Registry) Count

func (r *Registry) Count() int

Count returns the number of registered modules.

func (*Registry) Get

func (r *Registry) Get(name string) (Module, bool)

Get returns a module by name.

func (*Registry) GetMigrationInfo

func (r *Registry) GetMigrationInfo(moduleName string) ([]MigrationInfo, error)

GetMigrationInfo returns detailed migration information for a specific module.

func (*Registry) InitAll

func (r *Registry) InitAll(ctx *Context) error

InitAll initializes all registered modules. Modules are initialized in registration order. Dependencies are checked before initialization.

func (*Registry) IsActive

func (r *Registry) IsActive(name string) bool

IsActive returns whether a module is active.

func (*Registry) List

func (r *Registry) List() []Module

List returns all registered modules in registration order.

func (*Registry) ListInfo

func (r *Registry) ListInfo() []Info

ListInfo returns information about all registered modules.

func (*Registry) ListSidebarModules

func (r *Registry) ListSidebarModules() []render.SidebarModule

ListSidebarModules returns modules that should appear in the admin sidebar. Implements render.SidebarModuleProvider interface.

func (*Registry) Register

func (r *Registry) Register(m Module) error

Register adds a module to the registry. Modules are registered in the order they are added.

func (*Registry) RouteAll

func (r *Registry) RouteAll(router chi.Router)

RouteAll registers all module public routes with active status middleware.

func (*Registry) SetActive

func (r *Registry) SetActive(name string, active bool) error

SetActive sets a module's active status and persists it to the database. When activating a module that was never initialized (e.g., it was inactive at server startup), Init() and translation loading are performed first.

func (*Registry) SetShowInSidebar

func (r *Registry) SetShowInSidebar(name string, show bool) error

SetShowInSidebar sets whether a module should appear in the admin sidebar.

func (*Registry) ShowInSidebar

func (r *Registry) ShowInSidebar(name string) bool

ShowInSidebar returns whether a module should be shown in the admin sidebar.

func (*Registry) ShutdownAll

func (r *Registry) ShutdownAll() error

ShutdownAll shuts down all modules in reverse order.

Jump to

Keyboard shortcuts

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