Files
poiesis/internal/functions/registry.go
2026-01-28 22:28:42 -05:00

87 lines
1.9 KiB
Go

package functions
import (
"fmt"
"reflect"
"strings"
"sync"
)
var (
functionRegistry = make(map[string]Function)
registryMutex sync.RWMutex
collector *typeCollector
)
func registerFunction[A Args, R any](name string, isAsync bool, fn GoFunc[A, R]) {
registryMutex.Lock()
defer registryMutex.Unlock()
if collector == nil {
collector = newTypeCollector()
}
tType := reflect.TypeFor[A]()
if tType.Kind() != reflect.Struct {
panic(fmt.Sprintf("function %s: argument must be a struct type, got %v", name, tType))
}
fnType := reflect.TypeOf(fn)
types := collector.collectTypes(tType, fnType)
paramTypes := collector.getParamTypes()
functionRegistry[name] = &functionImpl[A, R]{
name: name,
fn: fn,
types: types,
definition: generateTypeScriptDefinition(name, tType, fnType, isAsync, paramTypes),
isAsync: isAsync,
}
}
func GetFunctionDeclarations() string {
registryMutex.RLock()
defer registryMutex.RUnlock()
typeDefinitions := make(map[string]bool)
var typeDefs []string
var functionDecls []string
for _, fn := range functionRegistry {
for _, t := range fn.Types() {
if !typeDefinitions[t] {
typeDefinitions[t] = true
typeDefs = append(typeDefs, t)
}
}
functionDecls = append(functionDecls, fn.Definition())
}
result := strings.Join(typeDefs, "\n\n")
if len(result) > 0 && len(functionDecls) > 0 {
result += "\n\n"
}
result += strings.Join(functionDecls, "\n")
return result
}
func GetRegisteredFunctions() map[string]Function {
registryMutex.RLock()
defer registryMutex.RUnlock()
result := make(map[string]Function, len(functionRegistry))
for k, v := range functionRegistry {
result[k] = v
}
return result
}
func RegisterFunction[T Args, R any](name string, fn GoFunc[T, R]) {
registerFunction(name, false, fn)
}
func RegisterAsyncFunction[T Args, R any](name string, fn GoFunc[T, R]) {
registerFunction(name, true, fn)
}