fix(generator): error-only methods in response handling

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan 2025-12-23 17:41:29 -05:00
parent 097774f9c2
commit a0a5168f5f
4 changed files with 45 additions and 12 deletions

View File

@ -22,6 +22,7 @@ func GenerateService(svc Service, pkgName string) ([]byte, error) {
"needsJSON": NeedsJSON,
"needsRequestType": func(m Method) bool { return m.NeedsRequestType() },
"needsRespType": func(m Method) bool { return m.NeedsResponseType() },
"isErrorOnly": func(m Method) bool { return m.IsErrorOnly() },
"hasErrFromRead": hasErrorFromRead,
"readParam": generateReadParam,
"writeReturn": generateWriteReturn,
@ -292,14 +293,24 @@ func new{{$.Service.Name}}{{.Name}}HostFunction(service {{$.Service.Interface}})
{{- end}}
{{- if .HasError}}
if err != nil {
{{- if needsRespType .}}
{{- if isErrorOnly .}}
// Write error string to plugin memory
if ptr, err := p.WriteString(err.Error()); err == nil {
stack[0] = ptr
}
{{- else if needsRespType .}}
{{$.Service.Name | lower}}WriteError(p, stack, err)
{{- end}}
return
}
{{- end}}
{{- if needsRespType .}}
{{- if isErrorOnly .}}
// Write empty string to indicate success
if ptr, err := p.WriteString(""); err == nil {
stack[0] = ptr
}
{{- else if needsRespType .}}
// Write JSON response to plugin memory
resp := {{responseType .}}{
{{- range .Returns}}
@ -319,7 +330,7 @@ func new{{$.Service.Name}}{{.Name}}HostFunction(service {{$.Service.Interface}})
{{- else}}
[]extism.ValueType{ {{- range $i, $p := .Params}}{{if $i}}, {{end}}{{valueType $p.Type}}{{end}}{{if not .HasParams}}{{end}} },
{{- end}}
{{- if needsRespType .}}
{{- if or (needsRespType .) (isErrorOnly .)}}
[]extism.ValueType{extism.ValueTypePTR},
{{- else}}
[]extism.ValueType{ {{- range $i, $r := .Returns}}{{if $i}}, {{end}}{{valueType $r.Type}}{{end}}{{if not .HasReturns}}{{end}} },

View File

@ -176,14 +176,15 @@ func (m Method) NeedsRequestType() bool {
}
// NeedsResponseType returns true if a response struct is needed.
// Needed when we have complex returns that require JSON, or error handling.
// Needed when we have complex returns that require JSON (but not for error-only methods).
func (m Method) NeedsResponseType() bool {
// If there's an error, we need a response type to serialize it
if m.HasError {
// But only if there are also returns, or if returns need JSON
if m.HasReturns() {
return true
}
// Error-only methods return a simple string, not JSON
if m.IsErrorOnly() {
return false
}
// If there's an error with other returns, we need a response type
if m.HasError && m.HasReturns() {
return true
}
for _, r := range m.Returns {
if NeedsJSON(r.Type) {
@ -193,6 +194,11 @@ func (m Method) NeedsResponseType() bool {
return false
}
// IsErrorOnly returns true if the method only returns an error (no other return values).
func (m Method) IsErrorOnly() bool {
return m.HasError && !m.HasReturns()
}
// toJSONName converts a Go identifier to camelCase JSON field name.
func toJSONName(name string) string {
if name == "" {

View File

@ -75,11 +75,19 @@ func newMetaSetHostFunction(service MetaService) extism.HostFunction {
// Call the service method
err = service.Set(ctx, req.Data)
if err != nil {
// Write error string to plugin memory
if ptr, err := p.WriteString(err.Error()); err == nil {
stack[0] = ptr
}
return
}
// Write empty string to indicate success
if ptr, err := p.WriteString(""); err == nil {
stack[0] = ptr
}
},
[]extism.ValueType{extism.ValueTypePTR},
[]extism.ValueType{},
[]extism.ValueType{extism.ValueTypePTR},
)
}

View File

@ -24,10 +24,18 @@ func newPingPingHostFunction(service PingService) extism.HostFunction {
// Call the service method
err := service.Ping(ctx)
if err != nil {
// Write error string to plugin memory
if ptr, err := p.WriteString(err.Error()); err == nil {
stack[0] = ptr
}
return
}
// Write empty string to indicate success
if ptr, err := p.WriteString(""); err == nil {
stack[0] = ptr
}
},
[]extism.ValueType{},
[]extism.ValueType{},
[]extism.ValueType{extism.ValueTypePTR},
)
}