pobj

package module
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Jan 8, 2026 License: MIT Imports: 7 Imported by: 2

README

GoDoc

pobj

A Go object registry library that provides hierarchical type management, allowing types to be registered, instantiated by name, and accessed through a tree-like structure. It supports static methods, REST-like actions, and type-safe generic lookups.

Features

  • Hierarchical Registry - Organize types in a tree structure using path-based names (e.g., user/admin)
  • Type-Safe Generics - Uses Go 1.18+ generics for compile-time type safety
  • REST-like Actions - Built-in support for Fetch, List, Create, and Clear operations
  • Static Methods - Register type-level functions that can be called by name
  • Reflection-Based Instantiation - Create new instances of registered types at runtime
  • Context Support - All operations support context.Context for cancellation, timeouts, and passing contextual information (e.g., database connections, request metadata)

Installation

go get github.com/KarpelesLab/pobj

Quick Start

package main

import (
    "context"
    "fmt"

    "github.com/KarpelesLab/pobj"
    "github.com/KarpelesLab/typutil"
)

// Define your type
type User struct {
    ID    string
    Name  string
    Email string
}

func main() {
    // Register the type
    pobj.Register[User]("user")

    // Create a new instance
    obj := pobj.Get("user")
    instance := obj.New().(*User)
    instance.Name = "John Doe"

    fmt.Printf("Created user: %+v\n", instance)
}

Usage

Registering Types

Register a type with a path name:

// Simple registration
pobj.Register[User]("user")

// Nested registration (creates hierarchy)
pobj.Register[AdminUser]("user/admin")
pobj.Register[GuestUser]("user/guest")
Registering Actions

Register REST-like actions for a type:

actions := &pobj.ObjectActions{
    Fetch: typutil.Func(func(ctx context.Context, id string) (*User, error) {
        return fetchUserFromDB(id)
    }),
    List: typutil.Func(func(ctx context.Context) ([]*User, error) {
        return listUsersFromDB()
    }),
    Create: typutil.Func(func(ctx context.Context, data *User) (*User, error) {
        return createUserInDB(data)
    }),
    Clear: typutil.Func(func(ctx context.Context) error {
        return clearAllUsers()
    }),
}

pobj.RegisterActions[User]("user", actions)
Registering Static Methods

Register functions associated with a type (not instance methods):

// Format: "path:methodName"
pobj.RegisterStatic("user:getByEmail", func(ctx context.Context, email string) (*User, error) {
    return getUserByEmail(email)
})

// Call the static method
obj := pobj.Get("user")
method := obj.Static("getByEmail")
result, err := typutil.Call[*User](method, ctx, "user@example.com")
Retrieving Objects
// By path name
obj := pobj.Get("user")
obj = pobj.Get("user/admin")  // nested path

// By type (generic)
obj := pobj.GetByType[User]()

// Navigate hierarchy
root := pobj.Root()
child := root.Child("user")
Creating Instances
obj := pobj.Get("user")
instance := obj.New()  // returns any, type assert as needed

user := instance.(*User)
Fetching by ID

Using the registered Fetch action:

ctx := context.Background()

// Method 1: Via Object
obj := pobj.Get("user")
result, err := obj.ById(ctx, "user-123")
user := result.(*User)

// Method 2: Generic helper (type-safe)
user, err := pobj.ById[User](ctx, "user-123")

API Reference

Core Types
Object

Represents a registered type in the registry:

type Object struct {
    Action *ObjectActions  // REST-like actions (exported)
    // ... internal fields
}

Methods:

  • New() any - Create a new instance of the registered type
  • String() string - Get the full path name
  • Child(name string) *Object - Get a direct child object
  • Children() []string - Get names of all direct children
  • Static(name string) *typutil.Callable - Get a registered static method
  • ById(ctx context.Context, id string) (any, error) - Fetch instance by ID
ObjectActions

Defines factory functions for API operations:

type ObjectActions struct {
    Fetch  *typutil.Callable  // Get object by ID
    List   *typutil.Callable  // List all objects
    Create *typutil.Callable  // Create new object
    Clear  *typutil.Callable  // Delete all objects
}
Functions
Function Description
Register[T any](name string) *Object Register a type with a path name
RegisterActions[T any](name string, actions *ObjectActions) *Object Register a type with actions
RegisterStatic(name string, fn any) Register a static method (path:method format)
Get(name string) *Object Get object by path (returns nil if not found)
GetByType[T any]() *Object Get object by generic type
Root() *Object Get the root of the hierarchy
All() []*Object Get all registered objects (for introspection)
ById[T any](ctx, id string) (*T, error) Type-safe fetch by ID
Errors
Error Description
ErrUnknownType Type is not registered
ErrMissingAction Required action (e.g., Fetch) is not registered

Fetch Argument Format

The Fetch action supports two argument formats:

  1. String argument (recommended):

    func(ctx context.Context, id string) (*User, error)
    
  2. Struct argument (legacy):

    func(ctx context.Context, args struct{ Id string }) (*User, error)
    

The library automatically detects which format your Fetch function uses.

Panic Behavior

The following operations will panic:

  • Registering the same path twice with different types
  • Using invalid static method name format (missing :)
  • Passing a non-function to RegisterStatic

Dependencies

License

See LICENSE file.

Documentation

Overview

Package pobj provides an object registry system for Go, allowing types to be registered, instantiated by name, and accessed through a hierarchical structure. It supports static methods, object actions, and type-based lookup.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrUnknownType is returned when trying to get an object by a type
	// that hasn't been registered with the package. This typically occurs
	// when using GetByType[T]() or ById[T]() with an unregistered type.
	ErrUnknownType = errors.New("pobj: unknown object type")

	// ErrMissingAction is returned when trying to use an action (like Fetch)
	// that hasn't been registered for the object. This happens when an object
	// has no associated ObjectActions or when the specific action being used
	// is nil within the ObjectActions.
	ErrMissingAction = errors.New("pobj: no such action exists")
)

Sentinel errors for common failure cases.

Functions

func ById added in v0.1.0

func ById[T any](ctx context.Context, id string) (*T, error)

ById is a generic helper that fetches a typed object by its ID. It automatically looks up the registered type, calls its Fetch action, and returns a properly typed result.

Type parameter T should be the type you want to retrieve.

Parameters:

  • ctx: Context for the operation
  • id: Unique identifier for the object to fetch

Returns:

  • Pointer to the typed object or an error if:
  • The type T is not registered
  • The Fetch action fails
  • The returned object is not of the expected type

func Call deprecated added in v0.2.0

func Call[T any](s *typutil.Callable, ctx context.Context, arg ...any) (T, error)

Call calls the provided method and converts the result to the specified type T. This is a generic helper that handles type conversion of the return value.

Parameters:

  • s: The callable to invoke
  • ctx: Context for the operation
  • arg: Variable arguments to pass to the callable

Returns:

  • A value of type T and an error (if any)

Deprecated: use typutil.Call directly instead. This function is maintained for backward compatibility but will be removed in a future version.

func RegisterStatic

func RegisterStatic(name string, fn any)

RegisterStatic adds a static method to an object. The name must be in the format "object/path:methodName" where: - "object/path" is the registered object's path - "methodName" is the name of the static method The function fn will be converted to a callable using typutil.Func. Panics if the name format is invalid or the function cannot be converted. Deprecated: Use RegisterMethod instead which returns *Method for chaining.

func Static deprecated

func Static(method any) *typutil.Callable

Static returns a typutil.Callable object for a function that accepts a context.Context and/or a struct object as its arguments. This facilitates calling functions with dynamic arguments.

The function should follow the conventions expected by typutil.Func.

Deprecated: use typutil.Func directly instead. This function is maintained for backward compatibility but will be removed in a future version.

Types

type Field added in v0.2.2

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

Field represents metadata about a struct field.

func (*Field) Doc added in v0.2.2

func (f *Field) Doc() string

Doc returns the documentation for this field.

func (*Field) Name added in v0.2.2

func (f *Field) Name() string

Name returns the name of this field.

func (*Field) Object added in v0.2.2

func (f *Field) Object() *Object

Object returns the Object this field belongs to.

func (*Field) SetDoc added in v0.2.2

func (f *Field) SetDoc(doc string) *Field

SetDoc sets the documentation for this field and returns the field for chaining.

func (*Field) Type added in v0.2.2

func (f *Field) Type() reflect.Type

Type returns the reflect.Type of this field.

type Method added in v0.2.2

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

Method represents a registered method with its metadata. Methods can be either static (class-level) or require an instance in context.

func RegisterMethod added in v0.2.2

func RegisterMethod(name string, fn any) *Method

RegisterMethod adds a method to an object and returns the Method for further configuration. The name must be in the format "object/path:methodName" where: - "object/path" is the registered object's path - "methodName" is the name of the method The function fn will be converted to a callable using typutil.Func. Panics if the name format is invalid or the function cannot be converted.

The returned Method can be used to set documentation and other properties:

pobj.RegisterMethod("User:getByEmail", getByEmail).
    SetDoc("Fetch a user by their email address").
    SetRequiresInstance(false)

func (*Method) Callable added in v0.2.2

func (m *Method) Callable() *typutil.Callable

Callable returns the underlying typutil.Callable for this method.

func (*Method) Doc added in v0.2.2

func (m *Method) Doc() string

Doc returns the documentation for this method.

func (*Method) Name added in v0.2.2

func (m *Method) Name() string

Name returns the name of this method.

func (*Method) Object added in v0.2.2

func (m *Method) Object() *Object

Object returns the Object this method belongs to.

func (*Method) RequiresInstance added in v0.2.2

func (m *Method) RequiresInstance() bool

RequiresInstance returns true if this method requires an instance of the object to be provided in the context when called.

func (*Method) SetDoc added in v0.2.2

func (m *Method) SetDoc(doc string) *Method

SetDoc sets the documentation for this method and returns the method for method chaining.

func (*Method) SetRequiresInstance added in v0.2.2

func (m *Method) SetRequiresInstance(requires bool) *Method

SetRequiresInstance marks this method as requiring an instance of the object to be provided in the context. Returns the method for chaining.

func (*Method) String added in v0.2.2

func (m *Method) String() string

String returns the full path of this method in "object:method" format.

type Object

type Object struct {
	Action *ObjectActions // Actions that can be performed on this object type
	// contains filtered or unexported fields
}

Object represents a registered type in the object registry. Objects can be organized hierarchically with parent/child relationships.

func All added in v0.2.1

func All() []*Object

All returns all registered Objects that have an associated type. This can be used for introspection and debugging.

func Get added in v0.1.0

func Get(name string) *Object

Get returns the Object matching the given name, or nil if no such object exists. The name can be a path using '/' as separator for nested objects.

func GetByType added in v0.1.0

func GetByType[T any]() *Object

GetByType returns the Object matching the given generic type parameter. It handles pointer types by unwrapping them to their underlying type. Returns nil if the type is not registered.

func Register

func Register[T any](name string) *Object

Register adds a type to the registry with the given name. The type T is determined by the generic parameter. Name can be a path using '/' as separator for nested object registration. Returns the registered Object for further configuration. Panics if the name is already registered with a different type.

func RegisterActions

func RegisterActions[T any](name string, actions *ObjectActions) *Object

RegisterActions registers a type with associated actions for API operations. The actions include common operations like Fetch, List, Clear, and Create. Similar to Register, but also associates the ObjectActions with the registered type. Intended for implementing REST-like operations on the registered type. Returns the registered Object for further configuration. Panics if the name is already registered with a different type.

func Root

func Root() *Object

Root returns the root object holder, which is the top-level object in the hierarchical registry.

func (*Object) ById added in v0.1.1

func (o *Object) ById(ctx context.Context, id string) (any, error)

ById fetches an object instance by its ID using the object's Fetch action. This method requires the object to have a registered Fetch action. It automatically handles the appropriate argument passing format based on the Fetch action's signature.

Parameters:

  • ctx: Context for the operation
  • id: Unique identifier for the object to fetch

Returns:

  • The fetched object instance or an error if:
  • No Action or Fetch action is registered
  • The Fetch action fails

func (*Object) Child

func (o *Object) Child(name string) *Object

Child retrieves a direct child Object with the given name. Returns nil if the object has no children or the requested child doesn't exist.

func (*Object) Children added in v0.2.1

func (o *Object) Children() []string

Children returns the names of all direct child objects. Returns nil if the object has no children.

func (*Object) Doc added in v0.2.2

func (o *Object) Doc() string

Doc returns the documentation for this object.

func (*Object) Field added in v0.2.2

func (o *Object) Field(name string) *Field

Field returns the field metadata for the given field name. Returns nil if the field doesn't exist or has no metadata.

func (*Object) FieldDoc added in v0.2.2

func (o *Object) FieldDoc(fieldName string) string

FieldDoc returns the documentation for a field. Returns empty string if the field has no documentation.

func (*Object) Fields added in v0.2.2

func (o *Object) Fields() []string

Fields returns the names of all fields with metadata. Returns nil if the object has no field metadata.

func (*Object) Method added in v0.2.2

func (o *Object) Method(name string) *Method

Method returns the registered method with the given name. Unlike Static, this returns the Method struct which includes metadata such as documentation and whether the method requires an instance. Returns nil if the method doesn't exist.

func (*Object) Methods added in v0.2.2

func (o *Object) Methods() []string

Methods returns the names of all registered methods for this object. Returns nil if the object has no methods.

func (*Object) New

func (o *Object) New() any

New creates and returns a new instance of the registered type. Returns nil if the Object doesn't have an associated type. The returned value will be a pointer to a newly allocated instance.

func (*Object) SetDoc added in v0.2.2

func (o *Object) SetDoc(doc string) *Object

SetDoc sets the documentation for this object and returns the object for method chaining.

func (*Object) SetFieldDoc added in v0.2.2

func (o *Object) SetFieldDoc(fieldName, doc string) *Object

SetFieldDoc sets the documentation for a field and returns the object for chaining. If the field doesn't exist in the metadata, it will be created.

func (*Object) Static

func (o *Object) Static(name string) *typutil.Callable

Static returns the registered static method with the given name. Static methods are functions associated with an object type rather than with a specific instance of that type. Returns nil if the object has no static methods or the requested method doesn't exist.

func (*Object) String

func (o *Object) String() string

String returns the full path name of this Object in the registry hierarchy. The path uses '/' as a separator between parent and child objects.

type ObjectActions

type ObjectActions struct {
	Fetch  *typutil.Callable // Fetch retrieves a single object by ID
	List   *typutil.Callable // List returns all objects of this type
	Clear  *typutil.Callable // Clear deletes all objects of this type
	Create *typutil.Callable // Create instantiates a new object
}

ObjectActions defines callable factories for REST-like API operations. Each action is optional and can be set to nil if not needed.

Directories

Path Synopsis
cmd
pobj-docgen command
pobj-docgen extracts godoc comments and generates SetDoc calls for pobj registrations.
pobj-docgen extracts godoc comments and generates SetDoc calls for pobj registrations.

Jump to

Keyboard shortcuts

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