Files
poiesis/internal/builtin/typescript.go
2026-01-27 20:04:36 -05:00

74 lines
1.8 KiB
Go

package builtin
import (
"fmt"
"reflect"
"strings"
)
func getFieldName(field reflect.StructField) string {
jsonTag := field.Tag.Get("json")
if jsonTag != "" && jsonTag != "-" {
name, _, _ := strings.Cut(jsonTag, ",")
return name
}
return field.Name
}
func generateTypeScriptDefinition(name string, argsType reflect.Type, fnType reflect.Type, isPromise bool, paramTypes map[string]bool) string {
if argsType.Kind() != reflect.Struct {
return ""
}
var params []string
for i := 0; i < argsType.NumField(); i++ {
field := argsType.Field(i)
fieldName := getFieldName(field)
goType := field.Type
var tsType string
var isOptional bool
isPointer := goType.Kind() == reflect.Pointer
if isPointer {
isOptional = true
tsType = goTypeToTSType(goType, true)
if !strings.Contains(tsType, " | null") {
tsType += " | null"
}
} else {
isOptional = strings.Contains(field.Tag.Get("json"), ",omitempty")
tsType = goTypeToTSType(goType, false)
if isOptional && paramTypes[tsType+" | null"] {
tsType += " | null"
}
}
if isOptional {
fieldName += "?"
}
params = append(params, fmt.Sprintf("%s: %s", fieldName, tsType))
}
returnSignature := "any"
if fnType.Kind() == reflect.Func && fnType.NumOut() > 0 {
lastIndex := fnType.NumOut() - 1
lastType := fnType.Out(lastIndex)
if lastType.Implements(reflect.TypeOf((*error)(nil)).Elem()) {
if fnType.NumOut() > 1 {
returnType := fnType.Out(0)
returnSignature = goTypeToTSType(returnType, returnType.Kind() == reflect.Pointer)
}
} else {
returnSignature = goTypeToTSType(lastType, lastType.Kind() == reflect.Pointer)
}
}
if isPromise {
returnSignature = fmt.Sprintf("Promise<%s>", returnSignature)
}
return fmt.Sprintf("declare function %s(%s): %s;", name, strings.Join(params, ", "), returnSignature)
}