Help us shape the future of Go! Take the 2026 Go Developer Survey

menu

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package menu provides domain models and repository interfaces for menu management.

Index

Constants

View Source
const (
	LinkTypeEntity   = "entity"
	LinkTypeExternal = "external"
	LinkTypeArchive  = "archive"
	LinkTypeCustom   = "custom"
)

Link types for menu items.

View Source
const (
	LocationHeader  = "header"
	LocationFooter  = "footer"
	LocationSidebar = "sidebar"
)

Menu locations.

Variables

View Source
var (
	ErrMenuNotFound      = errors.New("menu not found")
	ErrMenuItemNotFound  = errors.New("menu item not found")
	ErrSlugAlreadyExists = errors.New("menu slug already exists")
	ErrInvalidLinkType   = errors.New("invalid link type")
	ErrInvalidLocation   = errors.New("invalid menu location")
	ErrEntityMissing     = errors.New("menu item links to an entity that does not exist")
	ErrCircularParent    = errors.New("circular parent reference")
)

Common errors.

Functions

func ValidLinkType

func ValidLinkType(lt string) bool

ValidLinkType checks if a link type is valid.

func ValidLocation

func ValidLocation(loc string) bool

ValidLocation checks if a menu location is valid.

Types

type CreateMenuInput

type CreateMenuInput struct {
	Name     string  `json:"name"`
	Slug     string  `json:"slug,omitempty"`
	Location *string `json:"location,omitempty"`
}

CreateMenuInput represents input for creating a new menu.

type CreateMenuItemInput

type CreateMenuItemInput struct {
	ParentID     *uuid.UUID `json:"parent_id,omitempty"`
	Label        string     `json:"label"`
	LinkType     string     `json:"link_type"`
	EntityID     *uuid.UUID `json:"entity_id,omitempty"`
	URL          *string    `json:"url,omitempty"`
	SchemaSlug   *string    `json:"schema_slug,omitempty"`
	Position     *int       `json:"position,omitempty"`
	OpenInNewTab bool       `json:"open_in_new_tab"`
	CSSClasses   *string    `json:"css_classes,omitempty"`
}

CreateMenuItemInput represents input for creating a menu item.

type Menu struct {
	ID        uuid.UUID   `json:"id"`
	Name      string      `json:"name"`
	Slug      string      `json:"slug"`
	Location  *string     `json:"location,omitempty"`
	Items     []*MenuItem `json:"items,omitempty"`
	CreatedAt time.Time   `json:"created_at"`
	UpdatedAt time.Time   `json:"updated_at"`
}

Menu represents a navigation menu.

type MenuItem struct {
	ID           uuid.UUID   `json:"id"`
	MenuID       uuid.UUID   `json:"menu_id"`
	ParentID     *uuid.UUID  `json:"parent_id,omitempty"`
	Label        string      `json:"label"`
	LinkType     string      `json:"link_type"` // entity, external, archive, custom
	EntityID     *uuid.UUID  `json:"entity_id,omitempty"`
	URL          *string     `json:"url,omitempty"`
	SchemaSlug   *string     `json:"schema_slug,omitempty"`
	Position     int         `json:"position"`
	OpenInNewTab bool        `json:"open_in_new_tab"`
	CSSClasses   *string     `json:"css_classes,omitempty"`
	Children     []*MenuItem `json:"children,omitempty"`
	CreatedAt    time.Time   `json:"created_at"`
	UpdatedAt    time.Time   `json:"updated_at"`

	// Computed from entity (not stored in DB)
	EntitySlug *string `json:"entity_slug,omitempty"`
	EntityName *string `json:"entity_name,omitempty"`
	// EntitySchemaSlug is the linked entity's schema (render-side URL
	// building); hidden from JSON so the API shape is unchanged.
	EntitySchemaSlug *string `json:"-"`
}

MenuItem represents a single item in a menu with optional nesting.

type PostgresRepository

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

PostgresRepository implements Repository using PostgreSQL.

func NewPostgresRepository

func NewPostgresRepository(db *database.DB) *PostgresRepository

NewPostgresRepository creates a new PostgreSQL menu repository.

func (*PostgresRepository) CreateMenu

func (r *PostgresRepository) CreateMenu(ctx context.Context, input *CreateMenuInput) (*Menu, error)

CreateMenu inserts a new menu.

func (*PostgresRepository) CreateMenuItem

func (r *PostgresRepository) CreateMenuItem(ctx context.Context, menuID uuid.UUID, input *CreateMenuItemInput) (*MenuItem, error)

CreateMenuItem inserts a new menu item.

func (*PostgresRepository) DeleteMenu

func (r *PostgresRepository) DeleteMenu(ctx context.Context, id uuid.UUID) error

DeleteMenu removes a menu and all its items.

func (*PostgresRepository) DeleteMenuItem

func (r *PostgresRepository) DeleteMenuItem(ctx context.Context, id uuid.UUID) error

DeleteMenuItem removes a menu item and reassigns children to parent.

func (*PostgresRepository) GetMenuByID

func (r *PostgresRepository) GetMenuByID(ctx context.Context, id uuid.UUID) (*Menu, error)

GetMenuByID retrieves a menu by ID.

func (*PostgresRepository) GetMenuByLocation

func (r *PostgresRepository) GetMenuByLocation(ctx context.Context, location string) (*Menu, error)

GetMenuByLocation retrieves a menu by location.

func (*PostgresRepository) GetMenuBySlug

func (r *PostgresRepository) GetMenuBySlug(ctx context.Context, slug string) (*Menu, error)

GetMenuBySlug retrieves a menu by slug.

func (*PostgresRepository) GetMenuItemByID

func (r *PostgresRepository) GetMenuItemByID(ctx context.Context, id uuid.UUID) (*MenuItem, error)

GetMenuItemByID retrieves a menu item by ID.

func (*PostgresRepository) GetMenuWithItems

func (r *PostgresRepository) GetMenuWithItems(ctx context.Context, menuID uuid.UUID) (*Menu, error)

GetMenuWithItems retrieves a menu with all items in nested structure.

func (*PostgresRepository) ListMenus

func (r *PostgresRepository) ListMenus(ctx context.Context) ([]*Menu, error)

ListMenus retrieves all menus for the tenant.

func (*PostgresRepository) ReorderItems

func (r *PostgresRepository) ReorderItems(ctx context.Context, menuID uuid.UUID, items []ReorderInput) error

ReorderItems updates positions and parent relationships for multiple items.

func (*PostgresRepository) ReplaceMenu

func (r *PostgresRepository) ReplaceMenu(ctx context.Context, id uuid.UUID, fields *UpdateMenuInput, items []ReplaceItem) error

ReplaceMenu implements Repository. The menu row is locked for the whole call, so concurrent replacements run one after the other.

func (*PostgresRepository) UpdateMenu

func (r *PostgresRepository) UpdateMenu(ctx context.Context, id uuid.UUID, input *UpdateMenuInput) (*Menu, error)

UpdateMenu modifies a menu.

func (*PostgresRepository) UpdateMenuItem

func (r *PostgresRepository) UpdateMenuItem(ctx context.Context, id uuid.UUID, input *UpdateMenuItemInput) (*MenuItem, error)

UpdateMenuItem modifies a menu item.

type ReorderInput

type ReorderInput struct {
	ID       uuid.UUID  `json:"id"`
	ParentID *uuid.UUID `json:"parent_id,omitempty"`
	Position int        `json:"position"`
}

ReorderInput represents a single item in a reorder request.

type ReplaceItem

type ReplaceItem struct {
	Label        string
	LinkType     string
	EntityID     *uuid.UUID
	URL          *string
	SchemaSlug   *string
	OpenInNewTab bool
	Parent       int
}

ReplaceItem is one item of a ReplaceMenu call. Parent is the index of an earlier item in the same list, or -1 for the top level.

type Repository

type Repository interface {
	// Menu operations
	CreateMenu(ctx context.Context, input *CreateMenuInput) (*Menu, error)
	GetMenuByID(ctx context.Context, id uuid.UUID) (*Menu, error)
	GetMenuBySlug(ctx context.Context, slug string) (*Menu, error)
	GetMenuByLocation(ctx context.Context, location string) (*Menu, error)
	ListMenus(ctx context.Context) ([]*Menu, error)
	UpdateMenu(ctx context.Context, id uuid.UUID, input *UpdateMenuInput) (*Menu, error)
	DeleteMenu(ctx context.Context, id uuid.UUID) error

	// Menu item operations
	CreateMenuItem(ctx context.Context, menuID uuid.UUID, input *CreateMenuItemInput) (*MenuItem, error)
	GetMenuItemByID(ctx context.Context, id uuid.UUID) (*MenuItem, error)
	UpdateMenuItem(ctx context.Context, id uuid.UUID, input *UpdateMenuItemInput) (*MenuItem, error)
	DeleteMenuItem(ctx context.Context, id uuid.UUID) error

	// Nested operations
	GetMenuWithItems(ctx context.Context, menuID uuid.UUID) (*Menu, error)
	ReorderItems(ctx context.Context, menuID uuid.UUID, items []ReorderInput) error

	// ReplaceMenu applies the menu fields (when set) and replaces every item
	// in one transaction: either all of it happens or none of it.
	ReplaceMenu(ctx context.Context, id uuid.UUID, fields *UpdateMenuInput, items []ReplaceItem) error
}

Repository defines the interface for menu data operations.

type Service

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

Service provides business logic for menu management.

func NewService

func NewService(repo Repository, logger *slog.Logger) *Service

NewService creates a new menu service.

func (*Service) CreateMenu

func (s *Service) CreateMenu(ctx context.Context, input *CreateMenuInput) (*Menu, error)

CreateMenu creates a new menu.

func (*Service) CreateMenuItem

func (s *Service) CreateMenuItem(ctx context.Context, menuID uuid.UUID, input *CreateMenuItemInput) (*MenuItem, error)

CreateMenuItem adds an item to a menu.

func (*Service) DeleteMenu

func (s *Service) DeleteMenu(ctx context.Context, id uuid.UUID) error

DeleteMenu removes a menu.

func (*Service) DeleteMenuItem

func (s *Service) DeleteMenuItem(ctx context.Context, id uuid.UUID) error

DeleteMenuItem removes a menu item.

func (*Service) GetMenu

func (s *Service) GetMenu(ctx context.Context, id uuid.UUID) (*Menu, error)

GetMenu retrieves a menu by ID.

func (*Service) GetMenuByLocation

func (s *Service) GetMenuByLocation(ctx context.Context, location string) (*Menu, error)

GetMenuByLocation retrieves a menu by location.

func (*Service) GetMenuBySlug

func (s *Service) GetMenuBySlug(ctx context.Context, slug string) (*Menu, error)

GetMenuBySlug retrieves a menu by slug.

func (*Service) GetMenuItem

func (s *Service) GetMenuItem(ctx context.Context, id uuid.UUID) (*MenuItem, error)

GetMenuItem retrieves a menu item by ID.

func (*Service) GetMenuWithItems

func (s *Service) GetMenuWithItems(ctx context.Context, menuID uuid.UUID) (*Menu, error)

GetMenuWithItems retrieves a menu with all nested items.

func (*Service) ListMenus

func (s *Service) ListMenus(ctx context.Context) ([]*Menu, error)

ListMenus retrieves all menus for the tenant.

func (*Service) ReorderItems

func (s *Service) ReorderItems(ctx context.Context, menuID uuid.UUID, items []ReorderInput) error

ReorderItems updates positions and parent relationships for multiple items.

func (*Service) ReplaceMenu

func (s *Service) ReplaceMenu(ctx context.Context, id uuid.UUID, fields *UpdateMenuInput, items []ReplaceItem) (*Menu, error)

ReplaceMenu updates a menu's name/location and replaces its items in one transaction. A nil items list leaves the items alone.

func (*Service) SetChangeObserver

func (s *Service) SetChangeObserver(f func(ctx context.Context))

SetChangeObserver installs the callback run after a menu or menu item was written; nil disables it.

func (*Service) UpdateMenu

func (s *Service) UpdateMenu(ctx context.Context, id uuid.UUID, input *UpdateMenuInput) (*Menu, error)

UpdateMenu modifies a menu.

func (*Service) UpdateMenuItem

func (s *Service) UpdateMenuItem(ctx context.Context, id uuid.UUID, input *UpdateMenuItemInput) (*MenuItem, error)

UpdateMenuItem modifies a menu item.

type UpdateMenuInput

type UpdateMenuInput struct {
	Name     *string `json:"name,omitempty"`
	Location *string `json:"location,omitempty"`
}

UpdateMenuInput represents input for updating a menu.

type UpdateMenuItemInput

type UpdateMenuItemInput struct {
	ParentID     *uuid.UUID `json:"parent_id,omitempty"`
	Label        *string    `json:"label,omitempty"`
	LinkType     *string    `json:"link_type,omitempty"`
	EntityID     *uuid.UUID `json:"entity_id,omitempty"`
	URL          *string    `json:"url,omitempty"`
	SchemaSlug   *string    `json:"schema_slug,omitempty"`
	Position     *int       `json:"position,omitempty"`
	OpenInNewTab *bool      `json:"open_in_new_tab,omitempty"`
	CSSClasses   *string    `json:"css_classes,omitempty"`
}

UpdateMenuItemInput represents input for updating a menu item.

Jump to

Keyboard shortcuts

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