mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-31 07:30:32 +00:00
refactor: host function wrappers to use structured request and response types
- Updated the host function signatures in `nd_host_artwork.go`, `nd_host_scheduler.go`, `nd_host_subsonicapi.go`, and `nd_host_websocket.go` to accept a single parameter for JSON requests. - Introduced structured request and response types for various cache operations in `nd_host_cache.go`. - Modified cache functions to marshal requests to JSON and unmarshal responses, improving error handling and code clarity. - Removed redundant memory allocation for string parameters in favor of JSON marshaling. - Enhanced error handling in WebSocket and cache operations to return structured error responses.
This commit is contained in:
parent
dd6a6e6ba7
commit
693ce7d280
@ -14,45 +14,23 @@ var templatesFS embed.FS
|
|||||||
// hostFuncMap returns the template functions for host code generation.
|
// hostFuncMap returns the template functions for host code generation.
|
||||||
func hostFuncMap(svc Service) template.FuncMap {
|
func hostFuncMap(svc Service) template.FuncMap {
|
||||||
return template.FuncMap{
|
return template.FuncMap{
|
||||||
"lower": strings.ToLower,
|
"lower": strings.ToLower,
|
||||||
"title": strings.Title,
|
"title": strings.Title,
|
||||||
"exportName": func(m Method) string { return m.FunctionName(svc.ExportPrefix()) },
|
"exportName": func(m Method) string { return m.FunctionName(svc.ExportPrefix()) },
|
||||||
"requestType": func(m Method) string { return m.RequestTypeName(svc.Name) },
|
"requestType": func(m Method) string { return m.RequestTypeName(svc.Name) },
|
||||||
"responseType": func(m Method) string { return m.ResponseTypeName(svc.Name) },
|
"responseType": func(m Method) string { return m.ResponseTypeName(svc.Name) },
|
||||||
"valueType": GoTypeToValueType,
|
|
||||||
"isSimple": IsSimpleType,
|
|
||||||
"isString": IsStringType,
|
|
||||||
"isBytes": IsBytesType,
|
|
||||||
"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,
|
|
||||||
"encodeReturn": generateEncodeReturn,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clientFuncMap returns the template functions for client code generation.
|
// clientFuncMap returns the template functions for client code generation.
|
||||||
func clientFuncMap(svc Service) template.FuncMap {
|
func clientFuncMap(svc Service) template.FuncMap {
|
||||||
return template.FuncMap{
|
return template.FuncMap{
|
||||||
"lower": strings.ToLower,
|
"lower": strings.ToLower,
|
||||||
"title": strings.Title,
|
"title": strings.Title,
|
||||||
"exportName": func(m Method) string { return m.FunctionName(svc.ExportPrefix()) },
|
"exportName": func(m Method) string { return m.FunctionName(svc.ExportPrefix()) },
|
||||||
"responseType": func(m Method) string { return m.ResponseTypeName(svc.Name) },
|
"requestType": func(m Method) string { return m.RequestTypeName(svc.Name) },
|
||||||
"isSimple": IsSimpleType,
|
"responseType": func(m Method) string { return m.ResponseTypeName(svc.Name) },
|
||||||
"isString": IsStringType,
|
"formatDoc": formatDoc,
|
||||||
"isBytes": IsBytesType,
|
|
||||||
"needsJSON": NeedsJSON,
|
|
||||||
"needsRespType": func(m Method) bool { return m.NeedsResponseType() },
|
|
||||||
"isErrorOnly": func(m Method) bool { return m.IsErrorOnly() },
|
|
||||||
"wasmParamType": wasmParamType,
|
|
||||||
"wasmReturnType": wasmReturnType,
|
|
||||||
"wrapperReturnType": func(m Method, svcName string) string { return wrapperReturnType(m, svcName) },
|
|
||||||
"clientCallArg": clientCallArg,
|
|
||||||
"decodeResult": decodeResult,
|
|
||||||
"formatDoc": formatDoc,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,11 +47,8 @@ func GenerateHost(svc Service, pkgName string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data := templateData{
|
data := templateData{
|
||||||
Package: pkgName,
|
Package: pkgName,
|
||||||
Service: svc,
|
Service: svc,
|
||||||
NeedsJSON: serviceNeedsJSON(svc),
|
|
||||||
NeedsWriteHelper: serviceNeedsWriteHelper(svc),
|
|
||||||
NeedsErrorHelper: serviceNeedsErrorHelper(svc),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@ -97,9 +72,7 @@ func GenerateClientGo(svc Service) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data := templateData{
|
data := templateData{
|
||||||
Service: svc,
|
Service: svc,
|
||||||
NeedsJSON: serviceClientNeedsJSON(svc),
|
|
||||||
NeedsErrors: serviceClientNeedsErrors(svc),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@ -111,269 +84,8 @@ func GenerateClientGo(svc Service) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type templateData struct {
|
type templateData struct {
|
||||||
Package string
|
Package string
|
||||||
Service Service
|
Service Service
|
||||||
NeedsJSON bool
|
|
||||||
NeedsErrors bool // Client: needs "errors" import
|
|
||||||
NeedsWriteHelper bool
|
|
||||||
NeedsErrorHelper bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// serviceNeedsJSON returns true if any method needs JSON encoding.
|
|
||||||
func serviceNeedsJSON(svc Service) bool {
|
|
||||||
for _, m := range svc.Methods {
|
|
||||||
for _, p := range m.Params {
|
|
||||||
if NeedsJSON(p.Type) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, r := range m.Returns {
|
|
||||||
if NeedsJSON(r.Type) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Error responses are also JSON
|
|
||||||
if m.HasError && m.NeedsResponseType() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// serviceNeedsWriteHelper returns true if any method needs the write helper.
|
|
||||||
func serviceNeedsWriteHelper(svc Service) bool {
|
|
||||||
for _, m := range svc.Methods {
|
|
||||||
if m.NeedsResponseType() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// serviceClientNeedsJSON returns true if any method needs JSON encoding in client code.
|
|
||||||
// This is true if any method has a response type (complex returns) or if any param/return needs JSON.
|
|
||||||
func serviceClientNeedsJSON(svc Service) bool {
|
|
||||||
for _, m := range svc.Methods {
|
|
||||||
// Response types use JSON for serialization
|
|
||||||
if m.NeedsResponseType() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// Parameters that need JSON marshaling
|
|
||||||
for _, p := range m.Params {
|
|
||||||
if NeedsJSON(p.Type) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// serviceClientNeedsErrors returns true if any method needs the errors package in client code.
|
|
||||||
// This is only true for error-only methods (methods that return just error).
|
|
||||||
func serviceClientNeedsErrors(svc Service) bool {
|
|
||||||
for _, m := range svc.Methods {
|
|
||||||
if m.IsErrorOnly() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// serviceNeedsErrorHelper returns true if any method needs error handling with JSON.
|
|
||||||
func serviceNeedsErrorHelper(svc Service) bool {
|
|
||||||
for _, m := range svc.Methods {
|
|
||||||
if m.HasError && m.NeedsResponseType() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// hasErrorFromRead returns true if reading params declares an err variable.
|
|
||||||
// This happens when using needsRequestType (JSON) or when any param is a PTR type.
|
|
||||||
func hasErrorFromRead(m Method) bool {
|
|
||||||
if m.NeedsRequestType() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
for _, p := range m.Params {
|
|
||||||
if IsStringType(p.Type) || IsBytesType(p.Type) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateReadParam generates code to read a parameter from the stack.
|
|
||||||
func generateReadParam(p Param, stackIndex int) string {
|
|
||||||
switch {
|
|
||||||
case IsSimpleType(p.Type):
|
|
||||||
return generateReadSimple(p, stackIndex)
|
|
||||||
case IsStringType(p.Type):
|
|
||||||
return fmt.Sprintf(`%s, err := p.ReadString(stack[%d])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}`, p.Name, stackIndex)
|
|
||||||
case IsBytesType(p.Type):
|
|
||||||
return fmt.Sprintf(`%s, err := p.ReadBytes(stack[%d])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}`, p.Name, stackIndex)
|
|
||||||
default:
|
|
||||||
// Complex type - JSON
|
|
||||||
return fmt.Sprintf(`%sBytes, err := p.ReadBytes(stack[%d])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var %s %s
|
|
||||||
if err := json.Unmarshal(%sBytes, &%s); err != nil {
|
|
||||||
return
|
|
||||||
}`, p.Name, stackIndex, p.Name, p.Type, p.Name, p.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateReadSimple generates code to read a simple type from the stack.
|
|
||||||
func generateReadSimple(p Param, stackIndex int) string {
|
|
||||||
switch p.Type {
|
|
||||||
case "int32":
|
|
||||||
return fmt.Sprintf(`%s := extism.DecodeI32(stack[%d])`, p.Name, stackIndex)
|
|
||||||
case "uint32":
|
|
||||||
return fmt.Sprintf(`%s := extism.DecodeU32(stack[%d])`, p.Name, stackIndex)
|
|
||||||
case "int64":
|
|
||||||
return fmt.Sprintf(`%s := int64(stack[%d])`, p.Name, stackIndex)
|
|
||||||
case "uint64":
|
|
||||||
return fmt.Sprintf(`%s := stack[%d]`, p.Name, stackIndex)
|
|
||||||
case "float32":
|
|
||||||
return fmt.Sprintf(`%s := extism.DecodeF32(stack[%d])`, p.Name, stackIndex)
|
|
||||||
case "float64":
|
|
||||||
return fmt.Sprintf(`%s := extism.DecodeF64(stack[%d])`, p.Name, stackIndex)
|
|
||||||
case "bool":
|
|
||||||
return fmt.Sprintf(`%s := extism.DecodeI32(stack[%d]) != 0`, p.Name, stackIndex)
|
|
||||||
default:
|
|
||||||
return fmt.Sprintf(`// FIXME: unsupported type: %s`, p.Type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateWriteReturn generates code to write a return value to the stack.
|
|
||||||
func generateWriteReturn(p Param, stackIndex int, varName string) string {
|
|
||||||
switch {
|
|
||||||
case IsSimpleType(p.Type):
|
|
||||||
return fmt.Sprintf(`stack[%d] = %s`, stackIndex, generateEncodeReturn(p, varName))
|
|
||||||
case IsStringType(p.Type):
|
|
||||||
return fmt.Sprintf(`if ptr, err := p.WriteString(%s); err == nil {
|
|
||||||
stack[%d] = ptr
|
|
||||||
}`, varName, stackIndex)
|
|
||||||
case IsBytesType(p.Type):
|
|
||||||
return fmt.Sprintf(`if ptr, err := p.WriteBytes(%s); err == nil {
|
|
||||||
stack[%d] = ptr
|
|
||||||
}`, varName, stackIndex)
|
|
||||||
default:
|
|
||||||
// Complex type - JSON
|
|
||||||
return fmt.Sprintf(`if bytes, err := json.Marshal(%s); err == nil {
|
|
||||||
if ptr, err := p.WriteBytes(bytes); err == nil {
|
|
||||||
stack[%d] = ptr
|
|
||||||
}
|
|
||||||
}`, varName, stackIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateEncodeReturn generates the encoding expression for a simple return.
|
|
||||||
func generateEncodeReturn(p Param, varName string) string {
|
|
||||||
switch p.Type {
|
|
||||||
case "int32":
|
|
||||||
return fmt.Sprintf("extism.EncodeI32(%s)", varName)
|
|
||||||
case "uint32":
|
|
||||||
return fmt.Sprintf("extism.EncodeU32(%s)", varName)
|
|
||||||
case "int64":
|
|
||||||
return fmt.Sprintf("uint64(%s)", varName)
|
|
||||||
case "uint64":
|
|
||||||
return varName
|
|
||||||
case "float32":
|
|
||||||
return fmt.Sprintf("extism.EncodeF32(%s)", varName)
|
|
||||||
case "float64":
|
|
||||||
return fmt.Sprintf("extism.EncodeF64(%s)", varName)
|
|
||||||
case "bool":
|
|
||||||
return fmt.Sprintf("func() uint64 { if %s { return 1 }; return 0 }()", varName)
|
|
||||||
default:
|
|
||||||
return "0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client-side helper functions for template
|
|
||||||
|
|
||||||
// wasmParamType returns the WASM parameter type for a Go parameter.
|
|
||||||
func wasmParamType(p Param) string {
|
|
||||||
if IsSimpleType(p.Type) {
|
|
||||||
return p.Type
|
|
||||||
}
|
|
||||||
// All pointer types (string, []byte, complex) use uint64 offset
|
|
||||||
return "uint64"
|
|
||||||
}
|
|
||||||
|
|
||||||
// wasmReturnType returns the WASM return type declaration for a method.
|
|
||||||
func wasmReturnType(m Method) string {
|
|
||||||
// Methods with JSON responses or error-only return uint64 (pointer)
|
|
||||||
if m.NeedsResponseType() || m.IsErrorOnly() {
|
|
||||||
return "uint64"
|
|
||||||
}
|
|
||||||
// Simple return types
|
|
||||||
if len(m.Returns) == 1 && IsSimpleType(m.Returns[0].Type) {
|
|
||||||
return m.Returns[0].Type
|
|
||||||
}
|
|
||||||
// No returns or multiple returns - use uint64 for pointer
|
|
||||||
if len(m.Returns) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return "uint64"
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrapperReturnType returns the Go return type for the wrapper function.
|
|
||||||
func wrapperReturnType(m Method, svcName string) string {
|
|
||||||
if m.NeedsResponseType() {
|
|
||||||
return fmt.Sprintf("(*%s%sResponse, error)", svcName, m.Name)
|
|
||||||
}
|
|
||||||
if m.IsErrorOnly() {
|
|
||||||
return "error"
|
|
||||||
}
|
|
||||||
if len(m.Returns) == 1 {
|
|
||||||
return m.Returns[0].Type
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// clientCallArg returns the argument expression for calling the host function.
|
|
||||||
func clientCallArg(p Param) string {
|
|
||||||
if IsSimpleType(p.Type) {
|
|
||||||
return p.Name
|
|
||||||
}
|
|
||||||
// Pointer types use .Offset()
|
|
||||||
return p.Name + "Mem.Offset()"
|
|
||||||
}
|
|
||||||
|
|
||||||
// decodeResult generates code to decode a simple return value.
|
|
||||||
func decodeResult(p Param, varName string) string {
|
|
||||||
switch p.Type {
|
|
||||||
case "int32":
|
|
||||||
return fmt.Sprintf("int32(%s)", varName)
|
|
||||||
case "uint32":
|
|
||||||
return fmt.Sprintf("uint32(%s)", varName)
|
|
||||||
case "int64":
|
|
||||||
return fmt.Sprintf("int64(%s)", varName)
|
|
||||||
case "uint64":
|
|
||||||
return varName
|
|
||||||
case "float32":
|
|
||||||
return fmt.Sprintf("math.Float32frombits(uint32(%s))", varName)
|
|
||||||
case "float64":
|
|
||||||
return fmt.Sprintf("math.Float64frombits(%s)", varName)
|
|
||||||
case "bool":
|
|
||||||
return fmt.Sprintf("%s != 0", varName)
|
|
||||||
case "string":
|
|
||||||
// pdk.FindMemory returns a value type, ReadBytes has pointer receiver
|
|
||||||
return fmt.Sprintf("func() string { m := pdk.FindMemory(%s); return string(m.ReadBytes()) }()", varName)
|
|
||||||
case "[]byte":
|
|
||||||
return fmt.Sprintf("func() []byte { m := pdk.FindMemory(%s); return m.ReadBytes() }()", varName)
|
|
||||||
default:
|
|
||||||
return varName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatDoc formats a documentation string for Go comments.
|
// formatDoc formats a documentation string for Go comments.
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import (
|
|||||||
var _ = Describe("Generator", func() {
|
var _ = Describe("Generator", func() {
|
||||||
Describe("GenerateHost", func() {
|
Describe("GenerateHost", func() {
|
||||||
It("should generate valid Go code for a simple service with strings", func() {
|
It("should generate valid Go code for a simple service with strings", func() {
|
||||||
// String params/returns don't need JSON - they use direct memory read/write
|
// All methods use JSON request/response types
|
||||||
svc := Service{
|
svc := Service{
|
||||||
Name: "SubsonicAPI",
|
Name: "SubsonicAPI",
|
||||||
Permission: "subsonicapi",
|
Permission: "subsonicapi",
|
||||||
@ -41,10 +41,11 @@ var _ = Describe("Generator", func() {
|
|||||||
// Check for package declaration
|
// Check for package declaration
|
||||||
Expect(codeStr).To(ContainSubstring("package host"))
|
Expect(codeStr).To(ContainSubstring("package host"))
|
||||||
|
|
||||||
// String params don't need request type - read directly from memory
|
// All methods now use request type for JSON protocol
|
||||||
Expect(codeStr).NotTo(ContainSubstring("type SubsonicAPICallRequest struct"))
|
Expect(codeStr).To(ContainSubstring("type SubsonicAPICallRequest struct"))
|
||||||
|
Expect(codeStr).To(ContainSubstring(`Uri string `))
|
||||||
|
|
||||||
// String return with error needs response type for error handling
|
// Response type with error handling
|
||||||
Expect(codeStr).To(ContainSubstring("type SubsonicAPICallResponse struct"))
|
Expect(codeStr).To(ContainSubstring("type SubsonicAPICallResponse struct"))
|
||||||
Expect(codeStr).To(ContainSubstring(`Response string `))
|
Expect(codeStr).To(ContainSubstring(`Response string `))
|
||||||
Expect(codeStr).To(ContainSubstring(`Error string `))
|
Expect(codeStr).To(ContainSubstring(`Error string `))
|
||||||
@ -55,8 +56,8 @@ var _ = Describe("Generator", func() {
|
|||||||
// Check for host function name
|
// Check for host function name
|
||||||
Expect(codeStr).To(ContainSubstring(`"subsonicapi_call"`))
|
Expect(codeStr).To(ContainSubstring(`"subsonicapi_call"`))
|
||||||
|
|
||||||
// Check for direct string read (not JSON unmarshal)
|
// Check for JSON unmarshal (all methods use JSON now)
|
||||||
Expect(codeStr).To(ContainSubstring("p.ReadString(stack[0])"))
|
Expect(codeStr).To(ContainSubstring("json.Unmarshal"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should generate code for methods without parameters", func() {
|
It("should generate code for methods without parameters", func() {
|
||||||
@ -80,8 +81,10 @@ var _ = Describe("Generator", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
codeStr := string(code)
|
codeStr := string(code)
|
||||||
// Should not have request type for methods without params
|
// Methods without params don't need a request type - no params to serialize
|
||||||
Expect(codeStr).NotTo(ContainSubstring("type TestNoParamsRequest struct"))
|
Expect(codeStr).NotTo(ContainSubstring("type TestNoParamsRequest struct"))
|
||||||
|
// But still uses PTR input/output for consistency
|
||||||
|
Expect(codeStr).To(MatchRegexp(`\[\]extism\.ValueType\{extism\.ValueTypePTR\},\s*\[\]extism\.ValueType\{extism\.ValueTypePTR\}`))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should generate code for methods without return values", func() {
|
It("should generate code for methods without return values", func() {
|
||||||
@ -144,8 +147,8 @@ var _ = Describe("Generator", func() {
|
|||||||
Expect(codeStr).To(ContainSubstring("scheduler_cancelschedule"))
|
Expect(codeStr).To(ContainSubstring("scheduler_cancelschedule"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should handle multiple simple parameters without JSON", func() {
|
It("should handle multiple simple parameters with JSON", func() {
|
||||||
// All simple params (string, int32, bool) can be passed on stack directly
|
// All params use JSON - single PTR input
|
||||||
svc := Service{
|
svc := Service{
|
||||||
Name: "Test",
|
Name: "Test",
|
||||||
Permission: "test",
|
Permission: "test",
|
||||||
@ -171,14 +174,12 @@ var _ = Describe("Generator", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
codeStr := string(code)
|
codeStr := string(code)
|
||||||
// No request type for simple params - they're read directly from stack
|
// All methods use request type with JSON protocol
|
||||||
Expect(codeStr).NotTo(ContainSubstring("type TestMultiParamRequest struct"))
|
Expect(codeStr).To(ContainSubstring("type TestMultiParamRequest struct"))
|
||||||
// Check for direct stack reads
|
// Check for JSON unmarshal (all methods use JSON now)
|
||||||
Expect(codeStr).To(ContainSubstring("p.ReadString(stack[0])"))
|
Expect(codeStr).To(ContainSubstring("json.Unmarshal"))
|
||||||
Expect(codeStr).To(ContainSubstring("extism.DecodeI32(stack[1])"))
|
// Check that input/output ValueType both use PTR (JSON)
|
||||||
Expect(codeStr).To(ContainSubstring("extism.DecodeI32(stack[2])"))
|
Expect(codeStr).To(MatchRegexp(`\[\]extism\.ValueType\{extism\.ValueTypePTR\},\s*\[\]extism\.ValueType\{extism\.ValueTypePTR\}`))
|
||||||
// Check that input ValueType slice has correct entries (3 params: PTR for string, I32 for int32, I32 for bool)
|
|
||||||
Expect(codeStr).To(ContainSubstring("extism.ValueTypePTR, extism.ValueTypeI32, extism.ValueTypeI32"))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should use single PTR for mixed simple and complex params", func() {
|
It("should use single PTR for mixed simple and complex params", func() {
|
||||||
@ -263,8 +264,8 @@ var _ = Describe("Generator", func() {
|
|||||||
Expect(codeStr).To(ContainSubstring(`extism "github.com/extism/go-sdk"`))
|
Expect(codeStr).To(ContainSubstring(`extism "github.com/extism/go-sdk"`))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should not include json import when not needed", func() {
|
It("should always include json import for JSON protocol", func() {
|
||||||
// Service with only simple types doesn't need JSON import
|
// All services use JSON protocol, so json import is always needed
|
||||||
svc := Service{
|
svc := Service{
|
||||||
Name: "Test",
|
Name: "Test",
|
||||||
Permission: "test",
|
Permission: "test",
|
||||||
@ -283,7 +284,7 @@ var _ = Describe("Generator", func() {
|
|||||||
|
|
||||||
codeStr := string(code)
|
codeStr := string(code)
|
||||||
Expect(codeStr).To(ContainSubstring(`"context"`))
|
Expect(codeStr).To(ContainSubstring(`"context"`))
|
||||||
Expect(codeStr).NotTo(ContainSubstring(`"encoding/json"`))
|
Expect(codeStr).To(ContainSubstring(`"encoding/json"`))
|
||||||
Expect(codeStr).To(ContainSubstring(`extism "github.com/extism/go-sdk"`))
|
Expect(codeStr).To(ContainSubstring(`extism "github.com/extism/go-sdk"`))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -8,12 +8,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
{{- if .NeedsJSON}}
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
{{- end}}
|
|
||||||
{{- if .NeedsErrors}}
|
|
||||||
"errors"
|
|
||||||
{{- end}}
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -24,12 +19,20 @@ import (
|
|||||||
// {{exportName .}} is the host function provided by Navidrome.
|
// {{exportName .}} is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user {{exportName .}}
|
//go:wasmimport extism:host/user {{exportName .}}
|
||||||
func {{exportName .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{wasmParamType $p}}{{end}}) {{wasmReturnType .}}
|
func {{exportName .}}(uint64) uint64
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
{{- /* Generate response types for methods that need them */ -}}
|
{{- /* Generate request/response types for all methods */ -}}
|
||||||
{{range .Service.Methods}}
|
{{range .Service.Methods}}
|
||||||
{{- if needsRespType .}}
|
{{- if .HasParams}}
|
||||||
|
|
||||||
|
// {{requestType .}} is the request type for {{$.Service.Name}}.{{.Name}}.
|
||||||
|
type {{requestType .}} struct {
|
||||||
|
{{- range .Params}}
|
||||||
|
{{title .Name}} {{.Type}} `json:"{{.JSONName}}"`
|
||||||
|
{{- end}}
|
||||||
|
}
|
||||||
|
{{- end}}
|
||||||
|
|
||||||
// {{responseType .}} is the response type for {{$.Service.Name}}.{{.Name}}.
|
// {{responseType .}} is the response type for {{$.Service.Name}}.{{.Name}}.
|
||||||
type {{responseType .}} struct {
|
type {{responseType .}} struct {
|
||||||
@ -39,7 +42,6 @@ type {{responseType .}} struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
{{- end}}
|
|
||||||
|
|
||||||
{{- /* Generate wrapper functions */ -}}
|
{{- /* Generate wrapper functions */ -}}
|
||||||
{{range .Service.Methods}}
|
{{range .Service.Methods}}
|
||||||
@ -48,28 +50,28 @@ type {{responseType .}} struct {
|
|||||||
{{- if .Doc}}
|
{{- if .Doc}}
|
||||||
{{formatDoc .Doc}}
|
{{formatDoc .Doc}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
func {{$.Service.Name}}{{.Name}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.Name}} {{$p.Type}}{{end}}) {{wrapperReturnType . $.Service.Name}} {
|
func {{$.Service.Name}}{{.Name}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.Name}} {{$p.Type}}{{end}}) (*{{responseType .}}, error) {
|
||||||
{{- if needsRespType .}}
|
{{- if .HasParams}}
|
||||||
{{- /* Complex response - use JSON */}}
|
// Marshal request to JSON
|
||||||
|
req := {{requestType .}}{
|
||||||
{{- range .Params}}
|
{{- range .Params}}
|
||||||
{{- if isString .Type}}
|
{{title .Name}}: {{.Name}},
|
||||||
{{.Name}}Mem := pdk.AllocateString({{.Name}})
|
{{- end}}
|
||||||
defer {{.Name}}Mem.Free()
|
}
|
||||||
{{- else if isBytes .Type}}
|
reqBytes, err := json.Marshal(req)
|
||||||
{{.Name}}Mem := pdk.AllocateBytes({{.Name}})
|
|
||||||
defer {{.Name}}Mem.Free()
|
|
||||||
{{- else if needsJSON .Type}}
|
|
||||||
{{.Name}}Bytes, err := json.Marshal({{.Name}})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
{{.Name}}Mem := pdk.AllocateBytes({{.Name}}Bytes)
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
defer {{.Name}}Mem.Free()
|
defer reqMem.Free()
|
||||||
{{- end}}
|
{{- else}}
|
||||||
|
// No parameters - allocate empty JSON object
|
||||||
|
reqMem := pdk.AllocateBytes([]byte("{}"))
|
||||||
|
defer reqMem.Free()
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := {{exportName .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{clientCallArg $p}}{{end}})
|
responsePtr := {{exportName .}}(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -82,56 +84,5 @@ func {{$.Service.Name}}{{.Name}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &response, nil
|
return &response, nil
|
||||||
{{- else if isErrorOnly .}}
|
|
||||||
{{- /* Error-only response - string result */}}
|
|
||||||
{{- range .Params}}
|
|
||||||
{{- if isString .Type}}
|
|
||||||
{{.Name}}Mem := pdk.AllocateString({{.Name}})
|
|
||||||
defer {{.Name}}Mem.Free()
|
|
||||||
{{- else if isBytes .Type}}
|
|
||||||
{{.Name}}Mem := pdk.AllocateBytes({{.Name}})
|
|
||||||
defer {{.Name}}Mem.Free()
|
|
||||||
{{- else if needsJSON .Type}}
|
|
||||||
{{.Name}}Bytes, err := json.Marshal({{.Name}})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
{{.Name}}Mem := pdk.AllocateBytes({{.Name}}Bytes)
|
|
||||||
defer {{.Name}}Mem.Free()
|
|
||||||
{{- end}}
|
|
||||||
{{- end}}
|
|
||||||
|
|
||||||
// Call the host function
|
|
||||||
responsePtr := {{exportName .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{clientCallArg $p}}{{end}})
|
|
||||||
|
|
||||||
// Read the response from memory
|
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
|
||||||
errStr := string(responseMem.ReadBytes())
|
|
||||||
|
|
||||||
if errStr != "" {
|
|
||||||
return errors.New(errStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
{{- else}}
|
|
||||||
{{- /* Simple return types - direct stack values */}}
|
|
||||||
{{- range .Params}}
|
|
||||||
{{- if isString .Type}}
|
|
||||||
{{.Name}}Mem := pdk.AllocateString({{.Name}})
|
|
||||||
defer {{.Name}}Mem.Free()
|
|
||||||
{{- else if isBytes .Type}}
|
|
||||||
{{.Name}}Mem := pdk.AllocateBytes({{.Name}})
|
|
||||||
defer {{.Name}}Mem.Free()
|
|
||||||
{{- end}}
|
|
||||||
{{- end}}
|
|
||||||
|
|
||||||
// Call the host function
|
|
||||||
{{- if .HasReturns}}
|
|
||||||
result := {{exportName .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{clientCallArg $p}}{{end}})
|
|
||||||
return {{decodeResult (index .Returns 0) "result"}}
|
|
||||||
{{- else}}
|
|
||||||
{{exportName .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{clientCallArg $p}}{{end}})
|
|
||||||
{{- end}}
|
|
||||||
{{- end}}
|
|
||||||
}
|
}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|||||||
@ -4,16 +4,14 @@ package {{.Package}}
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
{{- if .NeedsJSON}}
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
{{- end}}
|
|
||||||
|
|
||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
{{- /* Generate request/response types only when needed */ -}}
|
{{- /* Generate request/response types for all methods */ -}}
|
||||||
{{range .Service.Methods}}
|
{{range .Service.Methods}}
|
||||||
{{- if needsRequestType .}}
|
{{- if .HasParams}}
|
||||||
|
|
||||||
// {{requestType .}} is the request type for {{$.Service.Name}}.{{.Name}}.
|
// {{requestType .}} is the request type for {{$.Service.Name}}.{{.Name}}.
|
||||||
type {{requestType .}} struct {
|
type {{requestType .}} struct {
|
||||||
@ -22,7 +20,6 @@ type {{requestType .}} struct {
|
|||||||
{{- end}}
|
{{- end}}
|
||||||
}
|
}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
{{- if needsRespType .}}
|
|
||||||
|
|
||||||
// {{responseType .}} is the response type for {{$.Service.Name}}.{{.Name}}.
|
// {{responseType .}} is the response type for {{$.Service.Name}}.{{.Name}}.
|
||||||
type {{responseType .}} struct {
|
type {{responseType .}} struct {
|
||||||
@ -31,7 +28,6 @@ type {{responseType .}} struct {
|
|||||||
{{- end}}
|
{{- end}}
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
{{- end}}
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
// Register{{.Service.Name}}HostFunctions registers {{.Service.Name}} service host functions.
|
// Register{{.Service.Name}}HostFunctions registers {{.Service.Name}} service host functions.
|
||||||
@ -50,7 +46,6 @@ func new{{$.Service.Name}}{{.Name}}HostFunction(service {{$.Service.Interface}})
|
|||||||
"{{exportName .}}",
|
"{{exportName .}}",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
{{- if .HasParams}}
|
{{- if .HasParams}}
|
||||||
{{- if needsRequestType .}}
|
|
||||||
// Read JSON request from plugin memory
|
// Read JSON request from plugin memory
|
||||||
reqBytes, err := p.ReadBytes(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -62,47 +57,28 @@ func new{{$.Service.Name}}{{.Name}}HostFunction(service {{$.Service.Interface}})
|
|||||||
{{$.Service.Name | lower}}WriteError(p, stack, err)
|
{{$.Service.Name | lower}}WriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
{{- else}}
|
|
||||||
// Read parameters from stack
|
|
||||||
{{- range $i, $p := .Params}}
|
|
||||||
{{readParam $p $i}}
|
|
||||||
{{- end}}
|
|
||||||
{{- end}}
|
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
{{- $m := .}}
|
|
||||||
{{- if .HasReturns}}
|
{{- if .HasReturns}}
|
||||||
{{- if .HasError}}
|
{{- if .HasError}}
|
||||||
{{range $i, $r := .Returns}}{{if $i}}, {{end}}{{lower $r.Name}}{{end}}, err := service.{{.Name}}(ctx{{range .Params}}, {{if needsRequestType $m}}req.{{title .Name}}{{else}}{{.Name}}{{end}}{{end}})
|
{{range $i, $r := .Returns}}{{if $i}}, {{end}}{{lower $r.Name}}{{end}}, svcErr := service.{{.Name}}(ctx{{range .Params}}, req.{{title .Name}}{{end}})
|
||||||
{{- else}}
|
if svcErr != nil {
|
||||||
{{range $i, $r := .Returns}}{{if $i}}, {{end}}{{lower $r.Name}}{{end}} := service.{{.Name}}(ctx{{range .Params}}, {{if needsRequestType $m}}req.{{title .Name}}{{else}}{{.Name}}{{end}}{{end}})
|
{{$.Service.Name | lower}}WriteError(p, stack, svcErr)
|
||||||
{{- end}}
|
|
||||||
{{- else if .HasError}}
|
|
||||||
err {{if hasErrFromRead .}}={{else}}:={{end}} service.{{.Name}}(ctx{{range .Params}}, {{if needsRequestType $m}}req.{{title .Name}}{{else}}{{.Name}}{{end}}{{end}})
|
|
||||||
{{- else}}
|
|
||||||
service.{{.Name}}(ctx{{range .Params}}, {{if needsRequestType $m}}req.{{title .Name}}{{else}}{{.Name}}{{end}}{{end}})
|
|
||||||
{{- end}}
|
|
||||||
{{- if .HasError}}
|
|
||||||
if err != nil {
|
|
||||||
{{- 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
|
return
|
||||||
}
|
}
|
||||||
|
{{- else}}
|
||||||
|
{{range $i, $r := .Returns}}{{if $i}}, {{end}}{{lower $r.Name}}{{end}} := service.{{.Name}}(ctx{{range .Params}}, req.{{title .Name}}{{end}})
|
||||||
|
{{- end}}
|
||||||
|
{{- else if .HasError}}
|
||||||
|
if svcErr := service.{{.Name}}(ctx{{range .Params}}, req.{{title .Name}}{{end}}); svcErr != nil {
|
||||||
|
{{$.Service.Name | lower}}WriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
{{- else}}
|
||||||
|
service.{{.Name}}(ctx{{range .Params}}, req.{{title .Name}}{{end}})
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
{{- 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
|
// Write JSON response to plugin memory
|
||||||
resp := {{responseType .}}{
|
resp := {{responseType .}}{
|
||||||
{{- range .Returns}}
|
{{- range .Returns}}
|
||||||
@ -110,27 +86,12 @@ func new{{$.Service.Name}}{{.Name}}HostFunction(service {{$.Service.Interface}})
|
|||||||
{{- end}}
|
{{- end}}
|
||||||
}
|
}
|
||||||
{{$.Service.Name | lower}}WriteResponse(p, stack, resp)
|
{{$.Service.Name | lower}}WriteResponse(p, stack, resp)
|
||||||
{{- else if .HasReturns}}
|
|
||||||
// Write return values to stack
|
|
||||||
{{- range $i, $r := .Returns}}
|
|
||||||
{{writeReturn $r $i (lower $r.Name)}}
|
|
||||||
{{- end}}
|
|
||||||
{{- end}}
|
|
||||||
},
|
},
|
||||||
{{- if needsRequestType $m}}
|
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
{{- else}}
|
|
||||||
[]extism.ValueType{ {{- range $i, $p := .Params}}{{if $i}}, {{end}}{{valueType $p.Type}}{{end}}{{if not .HasParams}}{{end}} },
|
|
||||||
{{- end}}
|
|
||||||
{{- if or (needsRespType .) (isErrorOnly .)}}
|
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
{{- else}}
|
|
||||||
[]extism.ValueType{ {{- range $i, $r := .Returns}}{{if $i}}, {{end}}{{valueType $r.Type}}{{end}}{{if not .HasReturns}}{{end}} },
|
|
||||||
{{- end}}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{- if .NeedsWriteHelper}}
|
|
||||||
|
|
||||||
// {{.Service.Name | lower}}WriteResponse writes a JSON response to plugin memory.
|
// {{.Service.Name | lower}}WriteResponse writes a JSON response to plugin memory.
|
||||||
func {{.Service.Name | lower}}WriteResponse(p *extism.CurrentPlugin, stack []uint64, resp any) {
|
func {{.Service.Name | lower}}WriteResponse(p *extism.CurrentPlugin, stack []uint64, resp any) {
|
||||||
@ -146,8 +107,6 @@ func {{.Service.Name | lower}}WriteResponse(p *extism.CurrentPlugin, stack []uin
|
|||||||
}
|
}
|
||||||
stack[0] = respPtr
|
stack[0] = respPtr
|
||||||
}
|
}
|
||||||
{{- end}}
|
|
||||||
{{- if .NeedsErrorHelper}}
|
|
||||||
|
|
||||||
// {{.Service.Name | lower}}WriteError writes an error response to plugin memory.
|
// {{.Service.Name | lower}}WriteError writes an error response to plugin memory.
|
||||||
func {{.Service.Name | lower}}WriteError(p *extism.CurrentPlugin, stack []uint64, err error) {
|
func {{.Service.Name | lower}}WriteError(p *extism.CurrentPlugin, stack []uint64, err error) {
|
||||||
@ -158,4 +117,3 @@ func {{.Service.Name | lower}}WriteError(p *extism.CurrentPlugin, stack []uint64
|
|||||||
respPtr, _ := p.WriteBytes(respBytes)
|
respPtr, _ := p.WriteBytes(respBytes)
|
||||||
stack[0] = respPtr
|
stack[0] = respPtr
|
||||||
}
|
}
|
||||||
{{- end}}
|
|
||||||
|
|||||||
@ -77,128 +77,6 @@ func NewParam(name, typ string) Param {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSimple returns true if the type can be passed directly on the WASM stack
|
|
||||||
// without JSON serialization (primitive numeric types).
|
|
||||||
func (p Param) IsSimple() bool {
|
|
||||||
return IsSimpleType(p.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPTR returns true if the type should be passed via memory pointer
|
|
||||||
// (strings, bytes, and complex types that need JSON serialization).
|
|
||||||
func (p Param) IsPTR() bool {
|
|
||||||
return !p.IsSimple()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValueType returns the Extism ValueType constant name for this parameter.
|
|
||||||
func (p Param) ValueType() string {
|
|
||||||
return GoTypeToValueType(p.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSimpleType returns true if a Go type can be passed directly on WASM stack.
|
|
||||||
func IsSimpleType(typ string) bool {
|
|
||||||
switch typ {
|
|
||||||
case "int32", "uint32", "int64", "uint64", "float32", "float64", "bool":
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsStringType returns true if the type is a string.
|
|
||||||
func IsStringType(typ string) bool {
|
|
||||||
return typ == "string"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsBytesType returns true if the type is []byte.
|
|
||||||
func IsBytesType(typ string) bool {
|
|
||||||
return typ == "[]byte"
|
|
||||||
}
|
|
||||||
|
|
||||||
// NeedsJSON returns true if the type requires JSON serialization.
|
|
||||||
func NeedsJSON(typ string) bool {
|
|
||||||
if IsSimpleType(typ) || IsStringType(typ) || IsBytesType(typ) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// GoTypeToValueType returns the Extism ValueType constant for a Go type.
|
|
||||||
func GoTypeToValueType(typ string) string {
|
|
||||||
switch typ {
|
|
||||||
case "int32", "uint32":
|
|
||||||
return "extism.ValueTypeI32"
|
|
||||||
case "int64", "uint64":
|
|
||||||
return "extism.ValueTypeI64"
|
|
||||||
case "float32":
|
|
||||||
return "extism.ValueTypeF32"
|
|
||||||
case "float64":
|
|
||||||
return "extism.ValueTypeF64"
|
|
||||||
case "bool":
|
|
||||||
return "extism.ValueTypeI32" // bool as i32
|
|
||||||
default:
|
|
||||||
// strings, []byte, structs, maps, slices all use PTR (i64)
|
|
||||||
return "extism.ValueTypePTR"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AllParamsSimple returns true if all params can be passed on the stack.
|
|
||||||
func (m Method) AllParamsSimple() bool {
|
|
||||||
for _, p := range m.Params {
|
|
||||||
if !p.IsSimple() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// AllReturnsSimple returns true if all returns can be passed on the stack.
|
|
||||||
func (m Method) AllReturnsSimple() bool {
|
|
||||||
for _, r := range m.Returns {
|
|
||||||
if !r.IsSimple() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// NeedsRequestType returns true if a request struct is needed.
|
|
||||||
// Only needed when we have complex params that require JSON.
|
|
||||||
func (m Method) NeedsRequestType() bool {
|
|
||||||
if !m.HasParams() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, p := range m.Params {
|
|
||||||
if NeedsJSON(p.Type) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// NeedsResponseType returns true if a response struct is needed.
|
|
||||||
// Needed when we have complex returns that require JSON (but not for error-only methods).
|
|
||||||
func (m Method) NeedsResponseType() bool {
|
|
||||||
// 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) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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.
|
// toJSONName converts a Go identifier to camelCase JSON field name.
|
||||||
func toJSONName(name string) string {
|
func toJSONName(name string) string {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
|
|||||||
@ -18,6 +18,11 @@ import (
|
|||||||
//go:wasmimport extism:host/user codec_encode
|
//go:wasmimport extism:host/user codec_encode
|
||||||
func codec_encode(uint64) uint64
|
func codec_encode(uint64) uint64
|
||||||
|
|
||||||
|
// CodecEncodeRequest is the request type for Codec.Encode.
|
||||||
|
type CodecEncodeRequest struct {
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
// CodecEncodeResponse is the response type for Codec.Encode.
|
// CodecEncodeResponse is the response type for Codec.Encode.
|
||||||
type CodecEncodeResponse struct {
|
type CodecEncodeResponse struct {
|
||||||
Result []byte `json:"result,omitempty"`
|
Result []byte `json:"result,omitempty"`
|
||||||
@ -26,11 +31,19 @@ type CodecEncodeResponse struct {
|
|||||||
|
|
||||||
// CodecEncode calls the codec_encode host function.
|
// CodecEncode calls the codec_encode host function.
|
||||||
func CodecEncode(data []byte) (*CodecEncodeResponse, error) {
|
func CodecEncode(data []byte) (*CodecEncodeResponse, error) {
|
||||||
dataMem := pdk.AllocateBytes(data)
|
// Marshal request to JSON
|
||||||
defer dataMem.Free()
|
req := CodecEncodeRequest{
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := codec_encode(dataMem.Offset())
|
responsePtr := codec_encode(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
28
plugins/cmd/hostgen/testdata/codec_expected.go
vendored
28
plugins/cmd/hostgen/testdata/codec_expected.go
vendored
@ -9,6 +9,11 @@ import (
|
|||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CodecEncodeRequest is the request type for Codec.Encode.
|
||||||
|
type CodecEncodeRequest struct {
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
// CodecEncodeResponse is the response type for Codec.Encode.
|
// CodecEncodeResponse is the response type for Codec.Encode.
|
||||||
type CodecEncodeResponse struct {
|
type CodecEncodeResponse struct {
|
||||||
Result []byte `json:"result,omitempty"`
|
Result []byte `json:"result,omitempty"`
|
||||||
@ -27,18 +32,25 @@ func newCodecEncodeHostFunction(service CodecService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"codec_encode",
|
"codec_encode",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
data, err := p.ReadBytes(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
result, err := service.Encode(ctx, data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
codecWriteError(p, stack, err)
|
codecWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req CodecEncodeRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
codecWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
result, svcErr := service.Encode(ctx, req.Data)
|
||||||
|
if svcErr != nil {
|
||||||
|
codecWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := CodecEncodeResponse{
|
resp := CodecEncodeResponse{
|
||||||
Result: result,
|
Result: result,
|
||||||
|
|||||||
@ -8,20 +8,52 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
// counter_count is the host function provided by Navidrome.
|
// counter_count is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user counter_count
|
//go:wasmimport extism:host/user counter_count
|
||||||
func counter_count(uint64) int32
|
func counter_count(uint64) uint64
|
||||||
|
|
||||||
|
// CounterCountRequest is the request type for Counter.Count.
|
||||||
|
type CounterCountRequest struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CounterCountResponse is the response type for Counter.Count.
|
||||||
|
type CounterCountResponse struct {
|
||||||
|
Value int32 `json:"value,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// CounterCount calls the counter_count host function.
|
// CounterCount calls the counter_count host function.
|
||||||
func CounterCount(name string) int32 {
|
func CounterCount(name string) (*CounterCountResponse, error) {
|
||||||
nameMem := pdk.AllocateString(name)
|
// Marshal request to JSON
|
||||||
defer nameMem.Free()
|
req := CounterCountRequest{
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
result := counter_count(nameMem.Offset())
|
responsePtr := counter_count(reqMem.Offset())
|
||||||
return int32(result)
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response CounterCountResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
59
plugins/cmd/hostgen/testdata/counter_expected.go
vendored
59
plugins/cmd/hostgen/testdata/counter_expected.go
vendored
@ -4,10 +4,22 @@ package testpkg
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CounterCountRequest is the request type for Counter.Count.
|
||||||
|
type CounterCountRequest struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CounterCountResponse is the response type for Counter.Count.
|
||||||
|
type CounterCountResponse struct {
|
||||||
|
Value int32 `json:"value,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterCounterHostFunctions registers Counter service host functions.
|
// RegisterCounterHostFunctions registers Counter service host functions.
|
||||||
// The returned host functions should be added to the plugin's configuration.
|
// The returned host functions should be added to the plugin's configuration.
|
||||||
func RegisterCounterHostFunctions(service CounterService) []extism.HostFunction {
|
func RegisterCounterHostFunctions(service CounterService) []extism.HostFunction {
|
||||||
@ -20,18 +32,53 @@ func newCounterCountHostFunction(service CounterService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"counter_count",
|
"counter_count",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
name, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
counterWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req CounterCountRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
counterWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
value := service.Count(ctx, name)
|
value := service.Count(ctx, req.Name)
|
||||||
// Write return values to stack
|
|
||||||
stack[0] = extism.EncodeI32(value)
|
// Write JSON response to plugin memory
|
||||||
|
resp := CounterCountResponse{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
counterWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypeI32},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// counterWriteResponse writes a JSON response to plugin memory.
|
||||||
|
func counterWriteResponse(p *extism.CurrentPlugin, stack []uint64, resp any) {
|
||||||
|
respBytes, err := json.Marshal(resp)
|
||||||
|
if err != nil {
|
||||||
|
counterWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respPtr, err := p.WriteBytes(respBytes)
|
||||||
|
if err != nil {
|
||||||
|
stack[0] = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stack[0] = respPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
// counterWriteError writes an error response to plugin memory.
|
||||||
|
func counterWriteError(p *extism.CurrentPlugin, stack []uint64, err error) {
|
||||||
|
errResp := struct {
|
||||||
|
Error string `json:"error"`
|
||||||
|
}{Error: err.Error()}
|
||||||
|
respBytes, _ := json.Marshal(errResp)
|
||||||
|
respPtr, _ := p.WriteBytes(respBytes)
|
||||||
|
stack[0] = respPtr
|
||||||
|
}
|
||||||
|
|||||||
@ -18,6 +18,11 @@ import (
|
|||||||
//go:wasmimport extism:host/user echo_echo
|
//go:wasmimport extism:host/user echo_echo
|
||||||
func echo_echo(uint64) uint64
|
func echo_echo(uint64) uint64
|
||||||
|
|
||||||
|
// EchoEchoRequest is the request type for Echo.Echo.
|
||||||
|
type EchoEchoRequest struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
// EchoEchoResponse is the response type for Echo.Echo.
|
// EchoEchoResponse is the response type for Echo.Echo.
|
||||||
type EchoEchoResponse struct {
|
type EchoEchoResponse struct {
|
||||||
Reply string `json:"reply,omitempty"`
|
Reply string `json:"reply,omitempty"`
|
||||||
@ -26,11 +31,19 @@ type EchoEchoResponse struct {
|
|||||||
|
|
||||||
// EchoEcho calls the echo_echo host function.
|
// EchoEcho calls the echo_echo host function.
|
||||||
func EchoEcho(message string) (*EchoEchoResponse, error) {
|
func EchoEcho(message string) (*EchoEchoResponse, error) {
|
||||||
messageMem := pdk.AllocateString(message)
|
// Marshal request to JSON
|
||||||
defer messageMem.Free()
|
req := EchoEchoRequest{
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := echo_echo(messageMem.Offset())
|
responsePtr := echo_echo(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
28
plugins/cmd/hostgen/testdata/echo_expected.go
vendored
28
plugins/cmd/hostgen/testdata/echo_expected.go
vendored
@ -9,6 +9,11 @@ import (
|
|||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EchoEchoRequest is the request type for Echo.Echo.
|
||||||
|
type EchoEchoRequest struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
// EchoEchoResponse is the response type for Echo.Echo.
|
// EchoEchoResponse is the response type for Echo.Echo.
|
||||||
type EchoEchoResponse struct {
|
type EchoEchoResponse struct {
|
||||||
Reply string `json:"reply,omitempty"`
|
Reply string `json:"reply,omitempty"`
|
||||||
@ -27,18 +32,25 @@ func newEchoEchoHostFunction(service EchoService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"echo_echo",
|
"echo_echo",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
message, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
reply, err := service.Echo(ctx, message)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
echoWriteError(p, stack, err)
|
echoWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req EchoEchoRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
echoWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
reply, svcErr := service.Echo(ctx, req.Message)
|
||||||
|
if svcErr != nil {
|
||||||
|
echoWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := EchoEchoResponse{
|
resp := EchoEchoResponse{
|
||||||
Reply: reply,
|
Reply: reply,
|
||||||
|
|||||||
@ -16,7 +16,13 @@ import (
|
|||||||
// list_items is the host function provided by Navidrome.
|
// list_items is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user list_items
|
//go:wasmimport extism:host/user list_items
|
||||||
func list_items(uint64, uint64) uint64
|
func list_items(uint64) uint64
|
||||||
|
|
||||||
|
// ListItemsRequest is the request type for List.Items.
|
||||||
|
type ListItemsRequest struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Filter Filter `json:"filter"`
|
||||||
|
}
|
||||||
|
|
||||||
// ListItemsResponse is the response type for List.Items.
|
// ListItemsResponse is the response type for List.Items.
|
||||||
type ListItemsResponse struct {
|
type ListItemsResponse struct {
|
||||||
@ -26,17 +32,20 @@ type ListItemsResponse struct {
|
|||||||
|
|
||||||
// ListItems calls the list_items host function.
|
// ListItems calls the list_items host function.
|
||||||
func ListItems(name string, filter Filter) (*ListItemsResponse, error) {
|
func ListItems(name string, filter Filter) (*ListItemsResponse, error) {
|
||||||
nameMem := pdk.AllocateString(name)
|
// Marshal request to JSON
|
||||||
defer nameMem.Free()
|
req := ListItemsRequest{
|
||||||
filterBytes, err := json.Marshal(filter)
|
Name: name,
|
||||||
|
Filter: filter,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
filterMem := pdk.AllocateBytes(filterBytes)
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
defer filterMem.Free()
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := list_items(nameMem.Offset(), filterMem.Offset())
|
responsePtr := list_items(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
@ -46,11 +46,12 @@ func newListItemsHostFunction(service ListService) extism.HostFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
count, err := service.Items(ctx, req.Name, req.Filter)
|
count, svcErr := service.Items(ctx, req.Name, req.Filter)
|
||||||
if err != nil {
|
if svcErr != nil {
|
||||||
listWriteError(p, stack, err)
|
listWriteError(p, stack, svcErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := ListItemsResponse{
|
resp := ListItemsResponse{
|
||||||
Count: count,
|
Count: count,
|
||||||
|
|||||||
@ -16,7 +16,13 @@ import (
|
|||||||
// math_add is the host function provided by Navidrome.
|
// math_add is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user math_add
|
//go:wasmimport extism:host/user math_add
|
||||||
func math_add(int32, int32) uint64
|
func math_add(uint64) uint64
|
||||||
|
|
||||||
|
// MathAddRequest is the request type for Math.Add.
|
||||||
|
type MathAddRequest struct {
|
||||||
|
A int32 `json:"a"`
|
||||||
|
B int32 `json:"b"`
|
||||||
|
}
|
||||||
|
|
||||||
// MathAddResponse is the response type for Math.Add.
|
// MathAddResponse is the response type for Math.Add.
|
||||||
type MathAddResponse struct {
|
type MathAddResponse struct {
|
||||||
@ -26,9 +32,20 @@ type MathAddResponse struct {
|
|||||||
|
|
||||||
// MathAdd calls the math_add host function.
|
// MathAdd calls the math_add host function.
|
||||||
func MathAdd(a int32, b int32) (*MathAddResponse, error) {
|
func MathAdd(a int32, b int32) (*MathAddResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := MathAddRequest{
|
||||||
|
A: a,
|
||||||
|
B: b,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := math_add(a, b)
|
responsePtr := math_add(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
29
plugins/cmd/hostgen/testdata/math_expected.go
vendored
29
plugins/cmd/hostgen/testdata/math_expected.go
vendored
@ -9,6 +9,12 @@ import (
|
|||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MathAddRequest is the request type for Math.Add.
|
||||||
|
type MathAddRequest struct {
|
||||||
|
A int32 `json:"a"`
|
||||||
|
B int32 `json:"b"`
|
||||||
|
}
|
||||||
|
|
||||||
// MathAddResponse is the response type for Math.Add.
|
// MathAddResponse is the response type for Math.Add.
|
||||||
type MathAddResponse struct {
|
type MathAddResponse struct {
|
||||||
Result int32 `json:"result,omitempty"`
|
Result int32 `json:"result,omitempty"`
|
||||||
@ -27,23 +33,32 @@ func newMathAddHostFunction(service MathService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"math_add",
|
"math_add",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
a := extism.DecodeI32(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
b := extism.DecodeI32(stack[1])
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
result, err := service.Add(ctx, a, b)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mathWriteError(p, stack, err)
|
mathWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req MathAddRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
mathWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
result, svcErr := service.Add(ctx, req.A, req.B)
|
||||||
|
if svcErr != nil {
|
||||||
|
mathWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := MathAddResponse{
|
resp := MathAddResponse{
|
||||||
Result: result,
|
Result: result,
|
||||||
}
|
}
|
||||||
mathWriteResponse(p, stack, resp)
|
mathWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypeI32, extism.ValueTypeI32},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -24,19 +23,42 @@ func meta_get(uint64) uint64
|
|||||||
//go:wasmimport extism:host/user meta_set
|
//go:wasmimport extism:host/user meta_set
|
||||||
func meta_set(uint64) uint64
|
func meta_set(uint64) uint64
|
||||||
|
|
||||||
|
// MetaGetRequest is the request type for Meta.Get.
|
||||||
|
type MetaGetRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// MetaGetResponse is the response type for Meta.Get.
|
// MetaGetResponse is the response type for Meta.Get.
|
||||||
type MetaGetResponse struct {
|
type MetaGetResponse struct {
|
||||||
Value any `json:"value,omitempty"`
|
Value any `json:"value,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MetaSetRequest is the request type for Meta.Set.
|
||||||
|
type MetaSetRequest struct {
|
||||||
|
Data map[string]any `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MetaSetResponse is the response type for Meta.Set.
|
||||||
|
type MetaSetResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// MetaGet calls the meta_get host function.
|
// MetaGet calls the meta_get host function.
|
||||||
func MetaGet(key string) (*MetaGetResponse, error) {
|
func MetaGet(key string) (*MetaGetResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := MetaGetRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := meta_get(keyMem.Offset())
|
responsePtr := meta_get(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -52,24 +74,30 @@ func MetaGet(key string) (*MetaGetResponse, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MetaSet calls the meta_set host function.
|
// MetaSet calls the meta_set host function.
|
||||||
func MetaSet(data map[string]any) error {
|
func MetaSet(data map[string]any) (*MetaSetResponse, error) {
|
||||||
dataBytes, err := json.Marshal(data)
|
// Marshal request to JSON
|
||||||
if err != nil {
|
req := MetaSetRequest{
|
||||||
return err
|
Data: data,
|
||||||
}
|
}
|
||||||
dataMem := pdk.AllocateBytes(dataBytes)
|
reqBytes, err := json.Marshal(req)
|
||||||
defer dataMem.Free()
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := meta_set(dataMem.Offset())
|
responsePtr := meta_set(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response MetaSetResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
49
plugins/cmd/hostgen/testdata/meta_expected.go
vendored
49
plugins/cmd/hostgen/testdata/meta_expected.go
vendored
@ -9,6 +9,11 @@ import (
|
|||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MetaGetRequest is the request type for Meta.Get.
|
||||||
|
type MetaGetRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// MetaGetResponse is the response type for Meta.Get.
|
// MetaGetResponse is the response type for Meta.Get.
|
||||||
type MetaGetResponse struct {
|
type MetaGetResponse struct {
|
||||||
Value any `json:"value,omitempty"`
|
Value any `json:"value,omitempty"`
|
||||||
@ -20,6 +25,11 @@ type MetaSetRequest struct {
|
|||||||
Data map[string]any `json:"data"`
|
Data map[string]any `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MetaSetResponse is the response type for Meta.Set.
|
||||||
|
type MetaSetResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterMetaHostFunctions registers Meta service host functions.
|
// RegisterMetaHostFunctions registers Meta service host functions.
|
||||||
// The returned host functions should be added to the plugin's configuration.
|
// The returned host functions should be added to the plugin's configuration.
|
||||||
func RegisterMetaHostFunctions(service MetaService) []extism.HostFunction {
|
func RegisterMetaHostFunctions(service MetaService) []extism.HostFunction {
|
||||||
@ -33,18 +43,25 @@ func newMetaGetHostFunction(service MetaService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"meta_get",
|
"meta_get",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
value, err := service.Get(ctx, key)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
metaWriteError(p, stack, err)
|
metaWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req MetaGetRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
metaWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
value, svcErr := service.Get(ctx, req.Key)
|
||||||
|
if svcErr != nil {
|
||||||
|
metaWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := MetaGetResponse{
|
resp := MetaGetResponse{
|
||||||
Value: value,
|
Value: value,
|
||||||
@ -73,18 +90,14 @@ func newMetaSetHostFunction(service MetaService) extism.HostFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.Set(ctx, req.Data)
|
if svcErr := service.Set(ctx, req.Data); svcErr != nil {
|
||||||
if err != nil {
|
metaWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := MetaSetResponse{}
|
||||||
}
|
metaWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -16,21 +16,31 @@ import (
|
|||||||
// ping_ping is the host function provided by Navidrome.
|
// ping_ping is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user ping_ping
|
//go:wasmimport extism:host/user ping_ping
|
||||||
func ping_ping() uint64
|
func ping_ping(uint64) uint64
|
||||||
|
|
||||||
|
// PingPingResponse is the response type for Ping.Ping.
|
||||||
|
type PingPingResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// PingPing calls the ping_ping host function.
|
// PingPing calls the ping_ping host function.
|
||||||
func PingPing() error {
|
func PingPing() (*PingPingResponse, error) {
|
||||||
|
// No parameters - allocate empty JSON object
|
||||||
|
reqMem := pdk.AllocateBytes([]byte("{}"))
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := ping_ping()
|
responsePtr := ping_ping(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response PingPingResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
49
plugins/cmd/hostgen/testdata/ping_expected.go
vendored
49
plugins/cmd/hostgen/testdata/ping_expected.go
vendored
@ -4,10 +4,16 @@ package testpkg
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PingPingResponse is the response type for Ping.Ping.
|
||||||
|
type PingPingResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterPingHostFunctions registers Ping service host functions.
|
// RegisterPingHostFunctions registers Ping service host functions.
|
||||||
// The returned host functions should be added to the plugin's configuration.
|
// The returned host functions should be added to the plugin's configuration.
|
||||||
func RegisterPingHostFunctions(service PingService) []extism.HostFunction {
|
func RegisterPingHostFunctions(service PingService) []extism.HostFunction {
|
||||||
@ -22,20 +28,41 @@ func newPingPingHostFunction(service PingService) extism.HostFunction {
|
|||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err := service.Ping(ctx)
|
if svcErr := service.Ping(ctx); svcErr != nil {
|
||||||
if err != nil {
|
pingWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := PingPingResponse{}
|
||||||
}
|
pingWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pingWriteResponse writes a JSON response to plugin memory.
|
||||||
|
func pingWriteResponse(p *extism.CurrentPlugin, stack []uint64, resp any) {
|
||||||
|
respBytes, err := json.Marshal(resp)
|
||||||
|
if err != nil {
|
||||||
|
pingWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respPtr, err := p.WriteBytes(respBytes)
|
||||||
|
if err != nil {
|
||||||
|
stack[0] = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stack[0] = respPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
// pingWriteError writes an error response to plugin memory.
|
||||||
|
func pingWriteError(p *extism.CurrentPlugin, stack []uint64, err error) {
|
||||||
|
errResp := struct {
|
||||||
|
Error string `json:"error"`
|
||||||
|
}{Error: err.Error()}
|
||||||
|
respBytes, _ := json.Marshal(errResp)
|
||||||
|
respPtr, _ := p.WriteBytes(respBytes)
|
||||||
|
stack[0] = respPtr
|
||||||
|
}
|
||||||
|
|||||||
@ -18,6 +18,11 @@ import (
|
|||||||
//go:wasmimport extism:host/user search_find
|
//go:wasmimport extism:host/user search_find
|
||||||
func search_find(uint64) uint64
|
func search_find(uint64) uint64
|
||||||
|
|
||||||
|
// SearchFindRequest is the request type for Search.Find.
|
||||||
|
type SearchFindRequest struct {
|
||||||
|
Query string `json:"query"`
|
||||||
|
}
|
||||||
|
|
||||||
// SearchFindResponse is the response type for Search.Find.
|
// SearchFindResponse is the response type for Search.Find.
|
||||||
type SearchFindResponse struct {
|
type SearchFindResponse struct {
|
||||||
Results []Result `json:"results,omitempty"`
|
Results []Result `json:"results,omitempty"`
|
||||||
@ -27,11 +32,19 @@ type SearchFindResponse struct {
|
|||||||
|
|
||||||
// SearchFind calls the search_find host function.
|
// SearchFind calls the search_find host function.
|
||||||
func SearchFind(query string) (*SearchFindResponse, error) {
|
func SearchFind(query string) (*SearchFindResponse, error) {
|
||||||
queryMem := pdk.AllocateString(query)
|
// Marshal request to JSON
|
||||||
defer queryMem.Free()
|
req := SearchFindRequest{
|
||||||
|
Query: query,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := search_find(queryMem.Offset())
|
responsePtr := search_find(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
28
plugins/cmd/hostgen/testdata/search_expected.go
vendored
28
plugins/cmd/hostgen/testdata/search_expected.go
vendored
@ -9,6 +9,11 @@ import (
|
|||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SearchFindRequest is the request type for Search.Find.
|
||||||
|
type SearchFindRequest struct {
|
||||||
|
Query string `json:"query"`
|
||||||
|
}
|
||||||
|
|
||||||
// SearchFindResponse is the response type for Search.Find.
|
// SearchFindResponse is the response type for Search.Find.
|
||||||
type SearchFindResponse struct {
|
type SearchFindResponse struct {
|
||||||
Results []Result `json:"results,omitempty"`
|
Results []Result `json:"results,omitempty"`
|
||||||
@ -28,18 +33,25 @@ func newSearchFindHostFunction(service SearchService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"search_find",
|
"search_find",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
query, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
results, total, err := service.Find(ctx, query)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
searchWriteError(p, stack, err)
|
searchWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req SearchFindRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
searchWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
results, total, svcErr := service.Find(ctx, req.Query)
|
||||||
|
if svcErr != nil {
|
||||||
|
searchWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := SearchFindResponse{
|
resp := SearchFindResponse{
|
||||||
Results: results,
|
Results: results,
|
||||||
|
|||||||
@ -18,6 +18,11 @@ import (
|
|||||||
//go:wasmimport extism:host/user store_save
|
//go:wasmimport extism:host/user store_save
|
||||||
func store_save(uint64) uint64
|
func store_save(uint64) uint64
|
||||||
|
|
||||||
|
// StoreSaveRequest is the request type for Store.Save.
|
||||||
|
type StoreSaveRequest struct {
|
||||||
|
Item Item `json:"item"`
|
||||||
|
}
|
||||||
|
|
||||||
// StoreSaveResponse is the response type for Store.Save.
|
// StoreSaveResponse is the response type for Store.Save.
|
||||||
type StoreSaveResponse struct {
|
type StoreSaveResponse struct {
|
||||||
Id string `json:"id,omitempty"`
|
Id string `json:"id,omitempty"`
|
||||||
@ -26,15 +31,19 @@ type StoreSaveResponse struct {
|
|||||||
|
|
||||||
// StoreSave calls the store_save host function.
|
// StoreSave calls the store_save host function.
|
||||||
func StoreSave(item Item) (*StoreSaveResponse, error) {
|
func StoreSave(item Item) (*StoreSaveResponse, error) {
|
||||||
itemBytes, err := json.Marshal(item)
|
// Marshal request to JSON
|
||||||
|
req := StoreSaveRequest{
|
||||||
|
Item: item,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
itemMem := pdk.AllocateBytes(itemBytes)
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
defer itemMem.Free()
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := store_save(itemMem.Offset())
|
responsePtr := store_save(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
@ -45,11 +45,12 @@ func newStoreSaveHostFunction(service StoreService) extism.HostFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
id, err := service.Save(ctx, req.Item)
|
id, svcErr := service.Save(ctx, req.Item)
|
||||||
if err != nil {
|
if svcErr != nil {
|
||||||
storeWriteError(p, stack, err)
|
storeWriteError(p, stack, svcErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := StoreSaveResponse{
|
resp := StoreSaveResponse{
|
||||||
Id: id,
|
Id: id,
|
||||||
|
|||||||
@ -16,7 +16,13 @@ import (
|
|||||||
// users_get is the host function provided by Navidrome.
|
// users_get is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user users_get
|
//go:wasmimport extism:host/user users_get
|
||||||
func users_get(uint64, uint64) uint64
|
func users_get(uint64) uint64
|
||||||
|
|
||||||
|
// UsersGetRequest is the request type for Users.Get.
|
||||||
|
type UsersGetRequest struct {
|
||||||
|
Id *string `json:"id"`
|
||||||
|
Filter *User `json:"filter"`
|
||||||
|
}
|
||||||
|
|
||||||
// UsersGetResponse is the response type for Users.Get.
|
// UsersGetResponse is the response type for Users.Get.
|
||||||
type UsersGetResponse struct {
|
type UsersGetResponse struct {
|
||||||
@ -26,21 +32,20 @@ type UsersGetResponse struct {
|
|||||||
|
|
||||||
// UsersGet calls the users_get host function.
|
// UsersGet calls the users_get host function.
|
||||||
func UsersGet(id *string, filter *User) (*UsersGetResponse, error) {
|
func UsersGet(id *string, filter *User) (*UsersGetResponse, error) {
|
||||||
idBytes, err := json.Marshal(id)
|
// Marshal request to JSON
|
||||||
|
req := UsersGetRequest{
|
||||||
|
Id: id,
|
||||||
|
Filter: filter,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
idMem := pdk.AllocateBytes(idBytes)
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
defer idMem.Free()
|
defer reqMem.Free()
|
||||||
filterBytes, err := json.Marshal(filter)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
filterMem := pdk.AllocateBytes(filterBytes)
|
|
||||||
defer filterMem.Free()
|
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := users_get(idMem.Offset(), filterMem.Offset())
|
responsePtr := users_get(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
@ -46,11 +46,12 @@ func newUsersGetHostFunction(service UsersService) extism.HostFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
result, err := service.Get(ctx, req.Id, req.Filter)
|
result, svcErr := service.Get(ctx, req.Id, req.Filter)
|
||||||
if err != nil {
|
if svcErr != nil {
|
||||||
usersWriteError(p, stack, err)
|
usersWriteError(p, stack, svcErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := UsersGetResponse{
|
resp := UsersGetResponse{
|
||||||
Result: result,
|
Result: result,
|
||||||
|
|||||||
@ -176,11 +176,14 @@ func parseTickerSymbols(tickerConfig string) []string {
|
|||||||
// connectAndSubscribe connects to Coinbase WebSocket and subscribes to tickers
|
// connectAndSubscribe connects to Coinbase WebSocket and subscribes to tickers
|
||||||
func connectAndSubscribe(tickers []string) error {
|
func connectAndSubscribe(tickers []string) error {
|
||||||
// Connect to WebSocket using host function
|
// Connect to WebSocket using host function
|
||||||
connID, err := WebSocketConnect(coinbaseWSEndpoint, nil, connectionID)
|
resp, err := WebSocketConnect(coinbaseWSEndpoint, nil, connectionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("WebSocket connection error: %v", err)
|
return fmt.Errorf("WebSocket connection error: %v", err)
|
||||||
}
|
}
|
||||||
pdk.Log(pdk.LogInfo, fmt.Sprintf("Connected to Coinbase WebSocket API (connection: %s)", connID))
|
if resp.Error != "" {
|
||||||
|
return fmt.Errorf("WebSocket connection error: %s", resp.Error)
|
||||||
|
}
|
||||||
|
pdk.Log(pdk.LogInfo, fmt.Sprintf("Connected to Coinbase WebSocket API (connection: %s)", resp.NewConnectionID))
|
||||||
|
|
||||||
// Subscribe to ticker channel
|
// Subscribe to ticker channel
|
||||||
subscription := CoinbaseSubscription{
|
subscription := CoinbaseSubscription{
|
||||||
@ -195,10 +198,13 @@ func connectAndSubscribe(tickers []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send subscription message
|
// Send subscription message
|
||||||
err = WebSocketSendText(connectionID, string(subscriptionJSON))
|
sendResp, err := WebSocketSendText(connectionID, string(subscriptionJSON))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("WebSocket send error: %v", err)
|
return fmt.Errorf("WebSocket send error: %v", err)
|
||||||
}
|
}
|
||||||
|
if sendResp.Error != "" {
|
||||||
|
return fmt.Errorf("WebSocket send error: %s", sendResp.Error)
|
||||||
|
}
|
||||||
|
|
||||||
pdk.Log(pdk.LogInfo, "Subscription message sent to Coinbase WebSocket API")
|
pdk.Log(pdk.LogInfo, "Subscription message sent to Coinbase WebSocket API")
|
||||||
return nil
|
return nil
|
||||||
@ -266,9 +272,11 @@ func NdWebsocketOnClose(input OnCloseInput) (OnCloseOutput, error) {
|
|||||||
pdk.Log(pdk.LogInfo, "Scheduling reconnection attempt in 5 seconds...")
|
pdk.Log(pdk.LogInfo, "Scheduling reconnection attempt in 5 seconds...")
|
||||||
|
|
||||||
// Schedule a one-time reconnection attempt
|
// Schedule a one-time reconnection attempt
|
||||||
_, err := SchedulerScheduleOneTime(5, "reconnect", reconnectScheduleID)
|
resp, err := SchedulerScheduleOneTime(5, "reconnect", reconnectScheduleID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pdk.Log(pdk.LogError, fmt.Sprintf("Failed to schedule reconnection: %v", err))
|
pdk.Log(pdk.LogError, fmt.Sprintf("Failed to schedule reconnection: %v", err))
|
||||||
|
} else if resp.Error != "" {
|
||||||
|
pdk.Log(pdk.LogError, fmt.Sprintf("Failed to schedule reconnection: %s", resp.Error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,9 +325,11 @@ func ndSchedulerCallback() int32 {
|
|||||||
pdk.Log(pdk.LogError, fmt.Sprintf("Reconnection failed: %v - will retry in 10 seconds", err))
|
pdk.Log(pdk.LogError, fmt.Sprintf("Reconnection failed: %v - will retry in 10 seconds", err))
|
||||||
|
|
||||||
// Schedule another attempt
|
// Schedule another attempt
|
||||||
_, err = SchedulerScheduleOneTime(10, "reconnect", reconnectScheduleID)
|
resp, err := SchedulerScheduleOneTime(10, "reconnect", reconnectScheduleID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pdk.Log(pdk.LogError, fmt.Sprintf("Failed to schedule retry: %v", err))
|
pdk.Log(pdk.LogError, fmt.Sprintf("Failed to schedule retry: %v", err))
|
||||||
|
} else if resp.Error != "" {
|
||||||
|
pdk.Log(pdk.LogError, fmt.Sprintf("Failed to schedule retry: %s", resp.Error))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pdk.Log(pdk.LogInfo, "Successfully reconnected!")
|
pdk.Log(pdk.LogInfo, "Successfully reconnected!")
|
||||||
|
|||||||
@ -1,188 +0,0 @@
|
|||||||
// Host function wrappers for Navidrome plugin services.
|
|
||||||
// These allow the plugin to call host functions provided by Navidrome.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
pdk "github.com/extism/go-pdk"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WebSocket host functions
|
|
||||||
|
|
||||||
//go:wasmimport extism:host/user websocket_connect
|
|
||||||
func websocket_connect(uint64) uint64
|
|
||||||
|
|
||||||
//go:wasmimport extism:host/user websocket_sendtext
|
|
||||||
func websocket_sendtext(connectionID uint64, message uint64) uint64
|
|
||||||
|
|
||||||
//go:wasmimport extism:host/user websocket_closeconnection
|
|
||||||
func websocket_closeconnection(connectionID uint64, code int32, reason uint64) uint64
|
|
||||||
|
|
||||||
// WebSocketConnectRequest is the request type for WebSocket.Connect
|
|
||||||
type WebSocketConnectRequest struct {
|
|
||||||
Url string `json:"url"`
|
|
||||||
Headers map[string]string `json:"headers,omitempty"`
|
|
||||||
ConnectionID string `json:"connectionID,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebSocketConnectResponse is the response type for WebSocket.Connect
|
|
||||||
type WebSocketConnectResponse struct {
|
|
||||||
NewConnectionID string `json:"newConnectionID,omitempty"`
|
|
||||||
Error string `json:"error,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebSocketConnect establishes a WebSocket connection to the specified URL.
|
|
||||||
func WebSocketConnect(url string, headers map[string]string, connectionID string) (string, error) {
|
|
||||||
req := WebSocketConnectRequest{
|
|
||||||
Url: url,
|
|
||||||
Headers: headers,
|
|
||||||
ConnectionID: connectionID,
|
|
||||||
}
|
|
||||||
reqBytes, err := json.Marshal(req)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
reqMem := pdk.AllocateBytes(reqBytes)
|
|
||||||
defer reqMem.Free()
|
|
||||||
|
|
||||||
responsePtr := websocket_connect(reqMem.Offset())
|
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
|
||||||
responseBytes := responseMem.ReadBytes()
|
|
||||||
|
|
||||||
var resp WebSocketConnectResponse
|
|
||||||
if err := json.Unmarshal(responseBytes, &resp); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Error != "" {
|
|
||||||
return "", errors.New(resp.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp.NewConnectionID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebSocketSendText sends a text message over an established WebSocket connection.
|
|
||||||
func WebSocketSendText(connectionID, message string) error {
|
|
||||||
connMem := pdk.AllocateString(connectionID)
|
|
||||||
defer connMem.Free()
|
|
||||||
msgMem := pdk.AllocateString(message)
|
|
||||||
defer msgMem.Free()
|
|
||||||
|
|
||||||
responsePtr := websocket_sendtext(connMem.Offset(), msgMem.Offset())
|
|
||||||
if responsePtr != 0 {
|
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
|
||||||
errStr := string(responseMem.ReadBytes())
|
|
||||||
if errStr != "" {
|
|
||||||
return errors.New(errStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebSocketCloseConnection gracefully closes a WebSocket connection.
|
|
||||||
func WebSocketCloseConnection(connectionID string, code int32, reason string) error {
|
|
||||||
connMem := pdk.AllocateString(connectionID)
|
|
||||||
defer connMem.Free()
|
|
||||||
reasonMem := pdk.AllocateString(reason)
|
|
||||||
defer reasonMem.Free()
|
|
||||||
|
|
||||||
responsePtr := websocket_closeconnection(connMem.Offset(), code, reasonMem.Offset())
|
|
||||||
if responsePtr != 0 {
|
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
|
||||||
errStr := string(responseMem.ReadBytes())
|
|
||||||
if errStr != "" {
|
|
||||||
return errors.New(errStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scheduler host functions
|
|
||||||
|
|
||||||
//go:wasmimport extism:host/user scheduler_scheduleonetime
|
|
||||||
func scheduler_scheduleonetime(delaySeconds int32, payload uint64, scheduleID uint64) uint64
|
|
||||||
|
|
||||||
//go:wasmimport extism:host/user scheduler_schedulerecurring
|
|
||||||
func scheduler_schedulerecurring(cronExpression uint64, payload uint64, scheduleID uint64) uint64
|
|
||||||
|
|
||||||
//go:wasmimport extism:host/user scheduler_cancelschedule
|
|
||||||
func scheduler_cancelschedule(scheduleID uint64) uint64
|
|
||||||
|
|
||||||
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime
|
|
||||||
type SchedulerScheduleOneTimeResponse struct {
|
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
|
||||||
Error string `json:"error,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring
|
|
||||||
type SchedulerScheduleRecurringResponse struct {
|
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
|
||||||
Error string `json:"error,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SchedulerScheduleOneTime schedules a one-time task to run after delaySeconds.
|
|
||||||
func SchedulerScheduleOneTime(delaySeconds int32, payload, scheduleID string) (string, error) {
|
|
||||||
payloadMem := pdk.AllocateString(payload)
|
|
||||||
defer payloadMem.Free()
|
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
|
||||||
defer scheduleIDMem.Free()
|
|
||||||
|
|
||||||
responsePtr := scheduler_scheduleonetime(delaySeconds, payloadMem.Offset(), scheduleIDMem.Offset())
|
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
|
||||||
responseBytes := responseMem.ReadBytes()
|
|
||||||
|
|
||||||
var resp SchedulerScheduleOneTimeResponse
|
|
||||||
if err := json.Unmarshal(responseBytes, &resp); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Error != "" {
|
|
||||||
return "", errors.New(resp.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp.NewScheduleID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SchedulerScheduleRecurring schedules a recurring task using a cron expression.
|
|
||||||
func SchedulerScheduleRecurring(cronExpression, payload, scheduleID string) (string, error) {
|
|
||||||
cronMem := pdk.AllocateString(cronExpression)
|
|
||||||
defer cronMem.Free()
|
|
||||||
payloadMem := pdk.AllocateString(payload)
|
|
||||||
defer payloadMem.Free()
|
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
|
||||||
defer scheduleIDMem.Free()
|
|
||||||
|
|
||||||
responsePtr := scheduler_schedulerecurring(cronMem.Offset(), payloadMem.Offset(), scheduleIDMem.Offset())
|
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
|
||||||
responseBytes := responseMem.ReadBytes()
|
|
||||||
|
|
||||||
var resp SchedulerScheduleRecurringResponse
|
|
||||||
if err := json.Unmarshal(responseBytes, &resp); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Error != "" {
|
|
||||||
return "", errors.New(resp.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp.NewScheduleID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SchedulerCancelSchedule cancels a scheduled task.
|
|
||||||
func SchedulerCancelSchedule(scheduleID string) error {
|
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
|
||||||
defer scheduleIDMem.Free()
|
|
||||||
|
|
||||||
responsePtr := scheduler_cancelschedule(scheduleIDMem.Offset())
|
|
||||||
if responsePtr != 0 {
|
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
|
||||||
errStr := string(responseMem.ReadBytes())
|
|
||||||
if errStr != "" {
|
|
||||||
return errors.New(errStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
180
plugins/examples/crypto-ticker/nd_host_scheduler.go
Normal file
180
plugins/examples/crypto-ticker/nd_host_scheduler.go
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
// Code generated by hostgen. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// This file contains client wrappers for the Scheduler host service.
|
||||||
|
// It is intended for use in Navidrome plugins built with TinyGo.
|
||||||
|
//
|
||||||
|
//go:build wasip1
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/extism/go-pdk"
|
||||||
|
)
|
||||||
|
|
||||||
|
// scheduler_scheduleonetime is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user scheduler_scheduleonetime
|
||||||
|
func scheduler_scheduleonetime(uint64) uint64
|
||||||
|
|
||||||
|
// scheduler_schedulerecurring is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user scheduler_schedulerecurring
|
||||||
|
func scheduler_schedulerecurring(uint64) uint64
|
||||||
|
|
||||||
|
// scheduler_cancelschedule is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user scheduler_cancelschedule
|
||||||
|
func scheduler_cancelschedule(uint64) uint64
|
||||||
|
|
||||||
|
// SchedulerScheduleOneTimeRequest is the request type for Scheduler.ScheduleOneTime.
|
||||||
|
type SchedulerScheduleOneTimeRequest struct {
|
||||||
|
DelaySeconds int32 `json:"delaySeconds"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
||||||
|
type SchedulerScheduleOneTimeResponse struct {
|
||||||
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerScheduleRecurringRequest is the request type for Scheduler.ScheduleRecurring.
|
||||||
|
type SchedulerScheduleRecurringRequest struct {
|
||||||
|
CronExpression string `json:"cronExpression"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
||||||
|
type SchedulerScheduleRecurringResponse struct {
|
||||||
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleRequest is the request type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleRequest struct {
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleResponse is the response type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerScheduleOneTime calls the scheduler_scheduleonetime host function.
|
||||||
|
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
|
||||||
|
// Plugins that use this function must also implement the SchedulerCallback capability
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - delaySeconds: Number of seconds to wait before triggering the event
|
||||||
|
// - payload: Data to be passed to the scheduled event handler
|
||||||
|
// - scheduleID: Optional unique identifier for the scheduled job. If empty, one will be generated
|
||||||
|
//
|
||||||
|
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||||
|
func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID string) (*SchedulerScheduleOneTimeResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := SchedulerScheduleOneTimeRequest{
|
||||||
|
DelaySeconds: delaySeconds,
|
||||||
|
Payload: payload,
|
||||||
|
ScheduleID: scheduleID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := scheduler_scheduleonetime(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response SchedulerScheduleOneTimeResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerScheduleRecurring calls the scheduler_schedulerecurring host function.
|
||||||
|
// ScheduleRecurring schedules a recurring event using a cron expression.
|
||||||
|
// Plugins that use this function must also implement the SchedulerCallback capability
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - cronExpression: Standard cron format expression (e.g., "0 0 * * *" for daily at midnight)
|
||||||
|
// - payload: Data to be passed to each scheduled event handler invocation
|
||||||
|
// - scheduleID: Optional unique identifier for the scheduled job. If empty, one will be generated
|
||||||
|
//
|
||||||
|
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||||
|
func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleID string) (*SchedulerScheduleRecurringResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := SchedulerScheduleRecurringRequest{
|
||||||
|
CronExpression: cronExpression,
|
||||||
|
Payload: payload,
|
||||||
|
ScheduleID: scheduleID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := scheduler_schedulerecurring(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response SchedulerScheduleRecurringResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelSchedule calls the scheduler_cancelschedule host function.
|
||||||
|
// CancelSchedule cancels a scheduled job identified by its schedule ID.
|
||||||
|
//
|
||||||
|
// This works for both one-time and recurring schedules. Once cancelled, the job will not trigger
|
||||||
|
// any future events.
|
||||||
|
//
|
||||||
|
// Returns an error if the schedule ID is not found or if cancellation fails.
|
||||||
|
func SchedulerCancelSchedule(scheduleID string) (*SchedulerCancelScheduleResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := SchedulerCancelScheduleRequest{
|
||||||
|
ScheduleID: scheduleID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := scheduler_cancelschedule(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response SchedulerCancelScheduleResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
237
plugins/examples/crypto-ticker/nd_host_websocket.go
Normal file
237
plugins/examples/crypto-ticker/nd_host_websocket.go
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
// Code generated by hostgen. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// This file contains client wrappers for the WebSocket host service.
|
||||||
|
// It is intended for use in Navidrome plugins built with TinyGo.
|
||||||
|
//
|
||||||
|
//go:build wasip1
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/extism/go-pdk"
|
||||||
|
)
|
||||||
|
|
||||||
|
// websocket_connect is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user websocket_connect
|
||||||
|
func websocket_connect(uint64) uint64
|
||||||
|
|
||||||
|
// websocket_sendtext is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user websocket_sendtext
|
||||||
|
func websocket_sendtext(uint64) uint64
|
||||||
|
|
||||||
|
// websocket_sendbinary is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user websocket_sendbinary
|
||||||
|
func websocket_sendbinary(uint64) uint64
|
||||||
|
|
||||||
|
// websocket_closeconnection is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user websocket_closeconnection
|
||||||
|
func websocket_closeconnection(uint64) uint64
|
||||||
|
|
||||||
|
// WebSocketConnectRequest is the request type for WebSocket.Connect.
|
||||||
|
type WebSocketConnectRequest struct {
|
||||||
|
Url string `json:"url"`
|
||||||
|
Headers map[string]string `json:"headers"`
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketConnectResponse is the response type for WebSocket.Connect.
|
||||||
|
type WebSocketConnectResponse struct {
|
||||||
|
NewConnectionID string `json:"newConnectionID,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextRequest is the request type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextResponse is the response type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryRequest is the request type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryResponse is the response type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionRequest is the request type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Code int32 `json:"code"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionResponse is the response type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketConnect calls the websocket_connect host function.
|
||||||
|
// Connect establishes a WebSocket connection to the specified URL.
|
||||||
|
//
|
||||||
|
// Plugins that use this function must also implement the WebSocketCallback capability
|
||||||
|
// to receive incoming messages and connection events.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - url: The WebSocket URL to connect to (ws:// or wss://)
|
||||||
|
// - headers: Optional HTTP headers to include in the handshake request
|
||||||
|
// - connectionID: Optional unique identifier for the connection. If empty, one will be generated
|
||||||
|
//
|
||||||
|
// Returns the connection ID that can be used to send messages or close the connection,
|
||||||
|
// or an error if the connection fails.
|
||||||
|
func WebSocketConnect(url string, headers map[string]string, connectionID string) (*WebSocketConnectResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := WebSocketConnectRequest{
|
||||||
|
Url: url,
|
||||||
|
Headers: headers,
|
||||||
|
ConnectionID: connectionID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := websocket_connect(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response WebSocketConnectResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendText calls the websocket_sendtext host function.
|
||||||
|
// SendText sends a text message over an established WebSocket connection.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - connectionID: The connection identifier returned by Connect
|
||||||
|
// - message: The text message to send
|
||||||
|
//
|
||||||
|
// Returns an error if the connection is not found or if sending fails.
|
||||||
|
func WebSocketSendText(connectionID string, message string) (*WebSocketSendTextResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := WebSocketSendTextRequest{
|
||||||
|
ConnectionID: connectionID,
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := websocket_sendtext(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response WebSocketSendTextResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinary calls the websocket_sendbinary host function.
|
||||||
|
// SendBinary sends binary data over an established WebSocket connection.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - connectionID: The connection identifier returned by Connect
|
||||||
|
// - data: The binary data to send
|
||||||
|
//
|
||||||
|
// Returns an error if the connection is not found or if sending fails.
|
||||||
|
func WebSocketSendBinary(connectionID string, data []byte) (*WebSocketSendBinaryResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := WebSocketSendBinaryRequest{
|
||||||
|
ConnectionID: connectionID,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := websocket_sendbinary(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response WebSocketSendBinaryResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnection calls the websocket_closeconnection host function.
|
||||||
|
// CloseConnection gracefully closes a WebSocket connection.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - connectionID: The connection identifier returned by Connect
|
||||||
|
// - code: WebSocket close status code (e.g., 1000 for normal closure)
|
||||||
|
// - reason: Optional human-readable reason for closing
|
||||||
|
//
|
||||||
|
// Returns an error if the connection is not found or if closing fails.
|
||||||
|
func WebSocketCloseConnection(connectionID string, code int32, reason string) (*WebSocketCloseConnectionResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := WebSocketCloseConnectionRequest{
|
||||||
|
ConnectionID: connectionID,
|
||||||
|
Code: code,
|
||||||
|
Reason: reason,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := websocket_closeconnection(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response WebSocketCloseConnectionResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
@ -181,7 +181,7 @@ func NdScrobblerNowPlaying(input NowPlayingInput) (ScrobblerOutput, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cancel any existing completion schedule
|
// Cancel any existing completion schedule
|
||||||
_ = SchedulerCancelSchedule(fmt.Sprintf("%s-clear", input.Username))
|
_, _ = SchedulerCancelSchedule(fmt.Sprintf("%s-clear", input.Username))
|
||||||
|
|
||||||
// Calculate timestamps
|
// Calculate timestamps
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
|
|||||||
@ -16,22 +16,28 @@ import (
|
|||||||
// artwork_getartisturl is the host function provided by Navidrome.
|
// artwork_getartisturl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_getartisturl
|
//go:wasmimport extism:host/user artwork_getartisturl
|
||||||
func artwork_getartisturl(uint64, int32) uint64
|
func artwork_getartisturl(uint64) uint64
|
||||||
|
|
||||||
// artwork_getalbumurl is the host function provided by Navidrome.
|
// artwork_getalbumurl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_getalbumurl
|
//go:wasmimport extism:host/user artwork_getalbumurl
|
||||||
func artwork_getalbumurl(uint64, int32) uint64
|
func artwork_getalbumurl(uint64) uint64
|
||||||
|
|
||||||
// artwork_gettrackurl is the host function provided by Navidrome.
|
// artwork_gettrackurl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_gettrackurl
|
//go:wasmimport extism:host/user artwork_gettrackurl
|
||||||
func artwork_gettrackurl(uint64, int32) uint64
|
func artwork_gettrackurl(uint64) uint64
|
||||||
|
|
||||||
// artwork_getplaylisturl is the host function provided by Navidrome.
|
// artwork_getplaylisturl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_getplaylisturl
|
//go:wasmimport extism:host/user artwork_getplaylisturl
|
||||||
func artwork_getplaylisturl(uint64, int32) uint64
|
func artwork_getplaylisturl(uint64) uint64
|
||||||
|
|
||||||
|
// ArtworkGetArtistUrlRequest is the request type for Artwork.GetArtistUrl.
|
||||||
|
type ArtworkGetArtistUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetArtistUrlResponse is the response type for Artwork.GetArtistUrl.
|
// ArtworkGetArtistUrlResponse is the response type for Artwork.GetArtistUrl.
|
||||||
type ArtworkGetArtistUrlResponse struct {
|
type ArtworkGetArtistUrlResponse struct {
|
||||||
@ -39,18 +45,36 @@ type ArtworkGetArtistUrlResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetAlbumUrlRequest is the request type for Artwork.GetAlbumUrl.
|
||||||
|
type ArtworkGetAlbumUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetAlbumUrlResponse is the response type for Artwork.GetAlbumUrl.
|
// ArtworkGetAlbumUrlResponse is the response type for Artwork.GetAlbumUrl.
|
||||||
type ArtworkGetAlbumUrlResponse struct {
|
type ArtworkGetAlbumUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetTrackUrlRequest is the request type for Artwork.GetTrackUrl.
|
||||||
|
type ArtworkGetTrackUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetTrackUrlResponse is the response type for Artwork.GetTrackUrl.
|
// ArtworkGetTrackUrlResponse is the response type for Artwork.GetTrackUrl.
|
||||||
type ArtworkGetTrackUrlResponse struct {
|
type ArtworkGetTrackUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetPlaylistUrlRequest is the request type for Artwork.GetPlaylistUrl.
|
||||||
|
type ArtworkGetPlaylistUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetPlaylistUrlResponse is the response type for Artwork.GetPlaylistUrl.
|
// ArtworkGetPlaylistUrlResponse is the response type for Artwork.GetPlaylistUrl.
|
||||||
type ArtworkGetPlaylistUrlResponse struct {
|
type ArtworkGetPlaylistUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
@ -66,11 +90,20 @@ type ArtworkGetPlaylistUrlResponse struct {
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetArtistUrl(id string, size int32) (*ArtworkGetArtistUrlResponse, error) {
|
func ArtworkGetArtistUrl(id string, size int32) (*ArtworkGetArtistUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetArtistUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_getartisturl(idMem.Offset(), size)
|
responsePtr := artwork_getartisturl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -94,11 +127,20 @@ func ArtworkGetArtistUrl(id string, size int32) (*ArtworkGetArtistUrlResponse, e
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetAlbumUrl(id string, size int32) (*ArtworkGetAlbumUrlResponse, error) {
|
func ArtworkGetAlbumUrl(id string, size int32) (*ArtworkGetAlbumUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetAlbumUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_getalbumurl(idMem.Offset(), size)
|
responsePtr := artwork_getalbumurl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -122,11 +164,20 @@ func ArtworkGetAlbumUrl(id string, size int32) (*ArtworkGetAlbumUrlResponse, err
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetTrackUrl(id string, size int32) (*ArtworkGetTrackUrlResponse, error) {
|
func ArtworkGetTrackUrl(id string, size int32) (*ArtworkGetTrackUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetTrackUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_gettrackurl(idMem.Offset(), size)
|
responsePtr := artwork_gettrackurl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -150,11 +201,20 @@ func ArtworkGetTrackUrl(id string, size int32) (*ArtworkGetTrackUrlResponse, err
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetPlaylistUrl(id string, size int32) (*ArtworkGetPlaylistUrlResponse, error) {
|
func ArtworkGetPlaylistUrl(id string, size int32) (*ArtworkGetPlaylistUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetPlaylistUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_getplaylisturl(idMem.Offset(), size)
|
responsePtr := artwork_getplaylisturl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
@ -9,7 +9,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -17,7 +16,7 @@ import (
|
|||||||
// cache_setstring is the host function provided by Navidrome.
|
// cache_setstring is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setstring
|
//go:wasmimport extism:host/user cache_setstring
|
||||||
func cache_setstring(uint64, uint64, int64) uint64
|
func cache_setstring(uint64) uint64
|
||||||
|
|
||||||
// cache_getstring is the host function provided by Navidrome.
|
// cache_getstring is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -27,7 +26,7 @@ func cache_getstring(uint64) uint64
|
|||||||
// cache_setint is the host function provided by Navidrome.
|
// cache_setint is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setint
|
//go:wasmimport extism:host/user cache_setint
|
||||||
func cache_setint(uint64, int64, int64) uint64
|
func cache_setint(uint64) uint64
|
||||||
|
|
||||||
// cache_getint is the host function provided by Navidrome.
|
// cache_getint is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -37,7 +36,7 @@ func cache_getint(uint64) uint64
|
|||||||
// cache_setfloat is the host function provided by Navidrome.
|
// cache_setfloat is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setfloat
|
//go:wasmimport extism:host/user cache_setfloat
|
||||||
func cache_setfloat(uint64, float64, int64) uint64
|
func cache_setfloat(uint64) uint64
|
||||||
|
|
||||||
// cache_getfloat is the host function provided by Navidrome.
|
// cache_getfloat is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -47,7 +46,7 @@ func cache_getfloat(uint64) uint64
|
|||||||
// cache_setbytes is the host function provided by Navidrome.
|
// cache_setbytes is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setbytes
|
//go:wasmimport extism:host/user cache_setbytes
|
||||||
func cache_setbytes(uint64, uint64, int64) uint64
|
func cache_setbytes(uint64) uint64
|
||||||
|
|
||||||
// cache_getbytes is the host function provided by Navidrome.
|
// cache_getbytes is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -64,6 +63,23 @@ func cache_has(uint64) uint64
|
|||||||
//go:wasmimport extism:host/user cache_remove
|
//go:wasmimport extism:host/user cache_remove
|
||||||
func cache_remove(uint64) uint64
|
func cache_remove(uint64) uint64
|
||||||
|
|
||||||
|
// CacheSetStringRequest is the request type for Cache.SetString.
|
||||||
|
type CacheSetStringRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetStringResponse is the response type for Cache.SetString.
|
||||||
|
type CacheSetStringResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetStringRequest is the request type for Cache.GetString.
|
||||||
|
type CacheGetStringRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetStringResponse is the response type for Cache.GetString.
|
// CacheGetStringResponse is the response type for Cache.GetString.
|
||||||
type CacheGetStringResponse struct {
|
type CacheGetStringResponse struct {
|
||||||
Value string `json:"value,omitempty"`
|
Value string `json:"value,omitempty"`
|
||||||
@ -71,6 +87,23 @@ type CacheGetStringResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetIntRequest is the request type for Cache.SetInt.
|
||||||
|
type CacheSetIntRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value int64 `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetIntResponse is the response type for Cache.SetInt.
|
||||||
|
type CacheSetIntResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetIntRequest is the request type for Cache.GetInt.
|
||||||
|
type CacheGetIntRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetIntResponse is the response type for Cache.GetInt.
|
// CacheGetIntResponse is the response type for Cache.GetInt.
|
||||||
type CacheGetIntResponse struct {
|
type CacheGetIntResponse struct {
|
||||||
Value int64 `json:"value,omitempty"`
|
Value int64 `json:"value,omitempty"`
|
||||||
@ -78,6 +111,23 @@ type CacheGetIntResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetFloatRequest is the request type for Cache.SetFloat.
|
||||||
|
type CacheSetFloatRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetFloatResponse is the response type for Cache.SetFloat.
|
||||||
|
type CacheSetFloatResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetFloatRequest is the request type for Cache.GetFloat.
|
||||||
|
type CacheGetFloatRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetFloatResponse is the response type for Cache.GetFloat.
|
// CacheGetFloatResponse is the response type for Cache.GetFloat.
|
||||||
type CacheGetFloatResponse struct {
|
type CacheGetFloatResponse struct {
|
||||||
Value float64 `json:"value,omitempty"`
|
Value float64 `json:"value,omitempty"`
|
||||||
@ -85,6 +135,23 @@ type CacheGetFloatResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetBytesRequest is the request type for Cache.SetBytes.
|
||||||
|
type CacheSetBytesRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value []byte `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetBytesResponse is the response type for Cache.SetBytes.
|
||||||
|
type CacheSetBytesResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetBytesRequest is the request type for Cache.GetBytes.
|
||||||
|
type CacheGetBytesRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetBytesResponse is the response type for Cache.GetBytes.
|
// CacheGetBytesResponse is the response type for Cache.GetBytes.
|
||||||
type CacheGetBytesResponse struct {
|
type CacheGetBytesResponse struct {
|
||||||
Value []byte `json:"value,omitempty"`
|
Value []byte `json:"value,omitempty"`
|
||||||
@ -92,12 +159,27 @@ type CacheGetBytesResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheHasRequest is the request type for Cache.Has.
|
||||||
|
type CacheHasRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheHasResponse is the response type for Cache.Has.
|
// CacheHasResponse is the response type for Cache.Has.
|
||||||
type CacheHasResponse struct {
|
type CacheHasResponse struct {
|
||||||
Exists bool `json:"exists,omitempty"`
|
Exists bool `json:"exists,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheRemoveRequest is the request type for Cache.Remove.
|
||||||
|
type CacheRemoveRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheRemoveResponse is the response type for Cache.Remove.
|
||||||
|
type CacheRemoveResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheSetString calls the cache_setstring host function.
|
// CacheSetString calls the cache_setstring host function.
|
||||||
// SetString stores a string value in the cache.
|
// SetString stores a string value in the cache.
|
||||||
//
|
//
|
||||||
@ -107,24 +189,34 @@ type CacheHasResponse struct {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetString(key string, value string, ttlSeconds int64) error {
|
func CacheSetString(key string, value string, ttlSeconds int64) (*CacheSetStringResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetStringRequest{
|
||||||
valueMem := pdk.AllocateString(value)
|
Key: key,
|
||||||
defer valueMem.Free()
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setstring(keyMem.Offset(), valueMem.Offset(), ttlSeconds)
|
responsePtr := cache_setstring(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetStringResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetString calls the cache_getstring host function.
|
// CacheGetString calls the cache_getstring host function.
|
||||||
@ -136,11 +228,19 @@ func CacheSetString(key string, value string, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not a string, exists will be false.
|
// or the stored value is not a string, exists will be false.
|
||||||
func CacheGetString(key string) (*CacheGetStringResponse, error) {
|
func CacheGetString(key string) (*CacheGetStringResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetStringRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getstring(keyMem.Offset())
|
responsePtr := cache_getstring(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -164,22 +264,34 @@ func CacheGetString(key string) (*CacheGetStringResponse, error) {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetInt(key string, value int64, ttlSeconds int64) error {
|
func CacheSetInt(key string, value int64, ttlSeconds int64) (*CacheSetIntResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetIntRequest{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setint(keyMem.Offset(), value, ttlSeconds)
|
responsePtr := cache_setint(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetIntResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetInt calls the cache_getint host function.
|
// CacheGetInt calls the cache_getint host function.
|
||||||
@ -191,11 +303,19 @@ func CacheSetInt(key string, value int64, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not an integer, exists will be false.
|
// or the stored value is not an integer, exists will be false.
|
||||||
func CacheGetInt(key string) (*CacheGetIntResponse, error) {
|
func CacheGetInt(key string) (*CacheGetIntResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetIntRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getint(keyMem.Offset())
|
responsePtr := cache_getint(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -219,22 +339,34 @@ func CacheGetInt(key string) (*CacheGetIntResponse, error) {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetFloat(key string, value float64, ttlSeconds int64) error {
|
func CacheSetFloat(key string, value float64, ttlSeconds int64) (*CacheSetFloatResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetFloatRequest{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setfloat(keyMem.Offset(), value, ttlSeconds)
|
responsePtr := cache_setfloat(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetFloatResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetFloat calls the cache_getfloat host function.
|
// CacheGetFloat calls the cache_getfloat host function.
|
||||||
@ -246,11 +378,19 @@ func CacheSetFloat(key string, value float64, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not a float, exists will be false.
|
// or the stored value is not a float, exists will be false.
|
||||||
func CacheGetFloat(key string) (*CacheGetFloatResponse, error) {
|
func CacheGetFloat(key string) (*CacheGetFloatResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetFloatRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getfloat(keyMem.Offset())
|
responsePtr := cache_getfloat(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -274,24 +414,34 @@ func CacheGetFloat(key string) (*CacheGetFloatResponse, error) {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetBytes(key string, value []byte, ttlSeconds int64) error {
|
func CacheSetBytes(key string, value []byte, ttlSeconds int64) (*CacheSetBytesResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetBytesRequest{
|
||||||
valueMem := pdk.AllocateBytes(value)
|
Key: key,
|
||||||
defer valueMem.Free()
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setbytes(keyMem.Offset(), valueMem.Offset(), ttlSeconds)
|
responsePtr := cache_setbytes(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetBytesResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetBytes calls the cache_getbytes host function.
|
// CacheGetBytes calls the cache_getbytes host function.
|
||||||
@ -303,11 +453,19 @@ func CacheSetBytes(key string, value []byte, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not a byte slice, exists will be false.
|
// or the stored value is not a byte slice, exists will be false.
|
||||||
func CacheGetBytes(key string) (*CacheGetBytesResponse, error) {
|
func CacheGetBytes(key string) (*CacheGetBytesResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetBytesRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getbytes(keyMem.Offset())
|
responsePtr := cache_getbytes(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -330,11 +488,19 @@ func CacheGetBytes(key string) (*CacheGetBytesResponse, error) {
|
|||||||
//
|
//
|
||||||
// Returns true if the key exists and has not expired.
|
// Returns true if the key exists and has not expired.
|
||||||
func CacheHas(key string) (*CacheHasResponse, error) {
|
func CacheHas(key string) (*CacheHasResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheHasRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_has(keyMem.Offset())
|
responsePtr := cache_has(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -356,20 +522,30 @@ func CacheHas(key string) (*CacheHasResponse, error) {
|
|||||||
// - key: The cache key (will be namespaced with plugin ID)
|
// - key: The cache key (will be namespaced with plugin ID)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails. Does not return an error if the key doesn't exist.
|
// Returns an error if the operation fails. Does not return an error if the key doesn't exist.
|
||||||
func CacheRemove(key string) error {
|
func CacheRemove(key string) (*CacheRemoveResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheRemoveRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_remove(keyMem.Offset())
|
responsePtr := cache_remove(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheRemoveResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -17,30 +16,54 @@ import (
|
|||||||
// scheduler_scheduleonetime is the host function provided by Navidrome.
|
// scheduler_scheduleonetime is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user scheduler_scheduleonetime
|
//go:wasmimport extism:host/user scheduler_scheduleonetime
|
||||||
func scheduler_scheduleonetime(int32, uint64, uint64) uint64
|
func scheduler_scheduleonetime(uint64) uint64
|
||||||
|
|
||||||
// scheduler_schedulerecurring is the host function provided by Navidrome.
|
// scheduler_schedulerecurring is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user scheduler_schedulerecurring
|
//go:wasmimport extism:host/user scheduler_schedulerecurring
|
||||||
func scheduler_schedulerecurring(uint64, uint64, uint64) uint64
|
func scheduler_schedulerecurring(uint64) uint64
|
||||||
|
|
||||||
// scheduler_cancelschedule is the host function provided by Navidrome.
|
// scheduler_cancelschedule is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user scheduler_cancelschedule
|
//go:wasmimport extism:host/user scheduler_cancelschedule
|
||||||
func scheduler_cancelschedule(uint64) uint64
|
func scheduler_cancelschedule(uint64) uint64
|
||||||
|
|
||||||
|
// SchedulerScheduleOneTimeRequest is the request type for Scheduler.ScheduleOneTime.
|
||||||
|
type SchedulerScheduleOneTimeRequest struct {
|
||||||
|
DelaySeconds int32 `json:"delaySeconds"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
||||||
type SchedulerScheduleOneTimeResponse struct {
|
type SchedulerScheduleOneTimeResponse struct {
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulerScheduleRecurringRequest is the request type for Scheduler.ScheduleRecurring.
|
||||||
|
type SchedulerScheduleRecurringRequest struct {
|
||||||
|
CronExpression string `json:"cronExpression"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
||||||
type SchedulerScheduleRecurringResponse struct {
|
type SchedulerScheduleRecurringResponse struct {
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleRequest is the request type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleRequest struct {
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleResponse is the response type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleOneTime calls the scheduler_scheduleonetime host function.
|
// SchedulerScheduleOneTime calls the scheduler_scheduleonetime host function.
|
||||||
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
|
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
|
||||||
// Plugins that use this function must also implement the SchedulerCallback capability
|
// Plugins that use this function must also implement the SchedulerCallback capability
|
||||||
@ -52,13 +75,21 @@ type SchedulerScheduleRecurringResponse struct {
|
|||||||
//
|
//
|
||||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||||
func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID string) (*SchedulerScheduleOneTimeResponse, error) {
|
func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID string) (*SchedulerScheduleOneTimeResponse, error) {
|
||||||
payloadMem := pdk.AllocateString(payload)
|
// Marshal request to JSON
|
||||||
defer payloadMem.Free()
|
req := SchedulerScheduleOneTimeRequest{
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
DelaySeconds: delaySeconds,
|
||||||
defer scheduleIDMem.Free()
|
Payload: payload,
|
||||||
|
ScheduleID: scheduleID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := scheduler_scheduleonetime(delaySeconds, payloadMem.Offset(), scheduleIDMem.Offset())
|
responsePtr := scheduler_scheduleonetime(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -84,15 +115,21 @@ func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID str
|
|||||||
//
|
//
|
||||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||||
func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleID string) (*SchedulerScheduleRecurringResponse, error) {
|
func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleID string) (*SchedulerScheduleRecurringResponse, error) {
|
||||||
cronExpressionMem := pdk.AllocateString(cronExpression)
|
// Marshal request to JSON
|
||||||
defer cronExpressionMem.Free()
|
req := SchedulerScheduleRecurringRequest{
|
||||||
payloadMem := pdk.AllocateString(payload)
|
CronExpression: cronExpression,
|
||||||
defer payloadMem.Free()
|
Payload: payload,
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
ScheduleID: scheduleID,
|
||||||
defer scheduleIDMem.Free()
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := scheduler_schedulerecurring(cronExpressionMem.Offset(), payloadMem.Offset(), scheduleIDMem.Offset())
|
responsePtr := scheduler_schedulerecurring(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -114,20 +151,30 @@ func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleI
|
|||||||
// any future events.
|
// any future events.
|
||||||
//
|
//
|
||||||
// Returns an error if the schedule ID is not found or if cancellation fails.
|
// Returns an error if the schedule ID is not found or if cancellation fails.
|
||||||
func SchedulerCancelSchedule(scheduleID string) error {
|
func SchedulerCancelSchedule(scheduleID string) (*SchedulerCancelScheduleResponse, error) {
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
// Marshal request to JSON
|
||||||
defer scheduleIDMem.Free()
|
req := SchedulerCancelScheduleRequest{
|
||||||
|
ScheduleID: scheduleID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := scheduler_cancelschedule(scheduleIDMem.Offset())
|
responsePtr := scheduler_cancelschedule(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response SchedulerCancelScheduleResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,13 +9,11 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
// websocket_connect is the host function provided by Navidrome.
|
// websocket_connect is the host function provided by Navidrome.
|
||||||
// Takes a single JSON request pointer containing url, headers, and connectionID.
|
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user websocket_connect
|
//go:wasmimport extism:host/user websocket_connect
|
||||||
func websocket_connect(uint64) uint64
|
func websocket_connect(uint64) uint64
|
||||||
@ -23,17 +21,17 @@ func websocket_connect(uint64) uint64
|
|||||||
// websocket_sendtext is the host function provided by Navidrome.
|
// websocket_sendtext is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user websocket_sendtext
|
//go:wasmimport extism:host/user websocket_sendtext
|
||||||
func websocket_sendtext(uint64, uint64) uint64
|
func websocket_sendtext(uint64) uint64
|
||||||
|
|
||||||
// websocket_sendbinary is the host function provided by Navidrome.
|
// websocket_sendbinary is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user websocket_sendbinary
|
//go:wasmimport extism:host/user websocket_sendbinary
|
||||||
func websocket_sendbinary(uint64, uint64) uint64
|
func websocket_sendbinary(uint64) uint64
|
||||||
|
|
||||||
// websocket_closeconnection is the host function provided by Navidrome.
|
// websocket_closeconnection is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user websocket_closeconnection
|
//go:wasmimport extism:host/user websocket_closeconnection
|
||||||
func websocket_closeconnection(uint64, int32, uint64) uint64
|
func websocket_closeconnection(uint64) uint64
|
||||||
|
|
||||||
// WebSocketConnectRequest is the request type for WebSocket.Connect.
|
// WebSocketConnectRequest is the request type for WebSocket.Connect.
|
||||||
type WebSocketConnectRequest struct {
|
type WebSocketConnectRequest struct {
|
||||||
@ -48,6 +46,40 @@ type WebSocketConnectResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextRequest is the request type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextResponse is the response type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryRequest is the request type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryResponse is the response type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionRequest is the request type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Code int32 `json:"code"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionResponse is the response type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// WebSocketConnect calls the websocket_connect host function.
|
// WebSocketConnect calls the websocket_connect host function.
|
||||||
// Connect establishes a WebSocket connection to the specified URL.
|
// Connect establishes a WebSocket connection to the specified URL.
|
||||||
//
|
//
|
||||||
@ -62,7 +94,7 @@ type WebSocketConnectResponse struct {
|
|||||||
// Returns the connection ID that can be used to send messages or close the connection,
|
// Returns the connection ID that can be used to send messages or close the connection,
|
||||||
// or an error if the connection fails.
|
// or an error if the connection fails.
|
||||||
func WebSocketConnect(url string, headers map[string]string, connectionID string) (*WebSocketConnectResponse, error) {
|
func WebSocketConnect(url string, headers map[string]string, connectionID string) (*WebSocketConnectResponse, error) {
|
||||||
// Create JSON request with all parameters
|
// Marshal request to JSON
|
||||||
req := WebSocketConnectRequest{
|
req := WebSocketConnectRequest{
|
||||||
Url: url,
|
Url: url,
|
||||||
Headers: headers,
|
Headers: headers,
|
||||||
@ -75,7 +107,7 @@ func WebSocketConnect(url string, headers map[string]string, connectionID string
|
|||||||
reqMem := pdk.AllocateBytes(reqBytes)
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
defer reqMem.Free()
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function with single JSON request
|
// Call the host function
|
||||||
responsePtr := websocket_connect(reqMem.Offset())
|
responsePtr := websocket_connect(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
@ -99,24 +131,33 @@ func WebSocketConnect(url string, headers map[string]string, connectionID string
|
|||||||
// - message: The text message to send
|
// - message: The text message to send
|
||||||
//
|
//
|
||||||
// Returns an error if the connection is not found or if sending fails.
|
// Returns an error if the connection is not found or if sending fails.
|
||||||
func WebSocketSendText(connectionID string, message string) error {
|
func WebSocketSendText(connectionID string, message string) (*WebSocketSendTextResponse, error) {
|
||||||
connectionIDMem := pdk.AllocateString(connectionID)
|
// Marshal request to JSON
|
||||||
defer connectionIDMem.Free()
|
req := WebSocketSendTextRequest{
|
||||||
messageMem := pdk.AllocateString(message)
|
ConnectionID: connectionID,
|
||||||
defer messageMem.Free()
|
Message: message,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := websocket_sendtext(connectionIDMem.Offset(), messageMem.Offset())
|
responsePtr := websocket_sendtext(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response WebSocketSendTextResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebSocketSendBinary calls the websocket_sendbinary host function.
|
// WebSocketSendBinary calls the websocket_sendbinary host function.
|
||||||
@ -127,24 +168,33 @@ func WebSocketSendText(connectionID string, message string) error {
|
|||||||
// - data: The binary data to send
|
// - data: The binary data to send
|
||||||
//
|
//
|
||||||
// Returns an error if the connection is not found or if sending fails.
|
// Returns an error if the connection is not found or if sending fails.
|
||||||
func WebSocketSendBinary(connectionID string, data []byte) error {
|
func WebSocketSendBinary(connectionID string, data []byte) (*WebSocketSendBinaryResponse, error) {
|
||||||
connectionIDMem := pdk.AllocateString(connectionID)
|
// Marshal request to JSON
|
||||||
defer connectionIDMem.Free()
|
req := WebSocketSendBinaryRequest{
|
||||||
dataMem := pdk.AllocateBytes(data)
|
ConnectionID: connectionID,
|
||||||
defer dataMem.Free()
|
Data: data,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := websocket_sendbinary(connectionIDMem.Offset(), dataMem.Offset())
|
responsePtr := websocket_sendbinary(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response WebSocketSendBinaryResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebSocketCloseConnection calls the websocket_closeconnection host function.
|
// WebSocketCloseConnection calls the websocket_closeconnection host function.
|
||||||
@ -156,22 +206,32 @@ func WebSocketSendBinary(connectionID string, data []byte) error {
|
|||||||
// - reason: Optional human-readable reason for closing
|
// - reason: Optional human-readable reason for closing
|
||||||
//
|
//
|
||||||
// Returns an error if the connection is not found or if closing fails.
|
// Returns an error if the connection is not found or if closing fails.
|
||||||
func WebSocketCloseConnection(connectionID string, code int32, reason string) error {
|
func WebSocketCloseConnection(connectionID string, code int32, reason string) (*WebSocketCloseConnectionResponse, error) {
|
||||||
connectionIDMem := pdk.AllocateString(connectionID)
|
// Marshal request to JSON
|
||||||
defer connectionIDMem.Free()
|
req := WebSocketCloseConnectionRequest{
|
||||||
reasonMem := pdk.AllocateString(reason)
|
ConnectionID: connectionID,
|
||||||
defer reasonMem.Free()
|
Code: code,
|
||||||
|
Reason: reason,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := websocket_closeconnection(connectionIDMem.Offset(), code, reasonMem.Offset())
|
responsePtr := websocket_closeconnection(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response WebSocketCloseConnectionResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,7 +140,7 @@ func processImage(imageURL, clientID, token string, isDefaultImage bool) (string
|
|||||||
ttl = 48 * 60 * 60 // 48 hours for default image
|
ttl = 48 * 60 * 60 // 48 hours for default image
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = CacheSetString(cacheKey, processedImage, ttl)
|
_, _ = CacheSetString(cacheKey, processedImage, ttl)
|
||||||
pdk.Log(pdk.LogDebug, fmt.Sprintf("Cached processed image URL for %s (TTL: %ds)", imageURL, ttl))
|
pdk.Log(pdk.LogDebug, fmt.Sprintf("Cached processed image URL for %s (TTL: %ds)", imageURL, ttl))
|
||||||
|
|
||||||
return processedImage, nil
|
return processedImage, nil
|
||||||
@ -183,9 +183,13 @@ func sendMessage(username string, opCode int, payload any) error {
|
|||||||
return fmt.Errorf("failed to marshal message: %w", err)
|
return fmt.Errorf("failed to marshal message: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := WebSocketSendText(username, string(b)); err != nil {
|
resp, err := WebSocketSendText(username, string(b))
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("failed to send message: %w", err)
|
return fmt.Errorf("failed to send message: %w", err)
|
||||||
}
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
return fmt.Errorf("failed to send message: %s", resp.Error)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,17 +224,21 @@ func cleanupFailedConnection(username string) {
|
|||||||
pdk.Log(pdk.LogInfo, fmt.Sprintf("Cleaning up failed connection for user %s", username))
|
pdk.Log(pdk.LogInfo, fmt.Sprintf("Cleaning up failed connection for user %s", username))
|
||||||
|
|
||||||
// Cancel the heartbeat schedule
|
// Cancel the heartbeat schedule
|
||||||
if err := SchedulerCancelSchedule(username); err != nil {
|
if resp, err := SchedulerCancelSchedule(username); err != nil {
|
||||||
pdk.Log(pdk.LogWarn, fmt.Sprintf("Failed to cancel heartbeat schedule for user %s: %v", username, err))
|
pdk.Log(pdk.LogWarn, fmt.Sprintf("Failed to cancel heartbeat schedule for user %s: %v", username, err))
|
||||||
|
} else if resp.Error != "" {
|
||||||
|
pdk.Log(pdk.LogWarn, fmt.Sprintf("Failed to cancel heartbeat schedule for user %s: %s", username, resp.Error))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the WebSocket connection
|
// Close the WebSocket connection
|
||||||
if err := WebSocketCloseConnection(username, 1000, "Connection lost"); err != nil {
|
if resp, err := WebSocketCloseConnection(username, 1000, "Connection lost"); err != nil {
|
||||||
pdk.Log(pdk.LogWarn, fmt.Sprintf("Failed to close WebSocket connection for user %s: %v", username, err))
|
pdk.Log(pdk.LogWarn, fmt.Sprintf("Failed to close WebSocket connection for user %s: %v", username, err))
|
||||||
|
} else if resp.Error != "" {
|
||||||
|
pdk.Log(pdk.LogWarn, fmt.Sprintf("Failed to close WebSocket connection for user %s: %s", username, resp.Error))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up cache entries
|
// Clean up cache entries
|
||||||
_ = CacheRemove(fmt.Sprintf("discord.seq.%s", username))
|
_, _ = CacheRemove(fmt.Sprintf("discord.seq.%s", username))
|
||||||
|
|
||||||
pdk.Log(pdk.LogInfo, fmt.Sprintf("Cleaned up connection for user %s", username))
|
pdk.Log(pdk.LogInfo, fmt.Sprintf("Cleaned up connection for user %s", username))
|
||||||
}
|
}
|
||||||
@ -297,12 +305,16 @@ func connect(username, token string) error {
|
|||||||
|
|
||||||
// disconnect closes the Discord connection for a user.
|
// disconnect closes the Discord connection for a user.
|
||||||
func disconnect(username string) error {
|
func disconnect(username string) error {
|
||||||
if err := SchedulerCancelSchedule(username); err != nil {
|
if resp, err := SchedulerCancelSchedule(username); err != nil {
|
||||||
return fmt.Errorf("failed to cancel schedule: %w", err)
|
return fmt.Errorf("failed to cancel schedule: %w", err)
|
||||||
|
} else if resp.Error != "" {
|
||||||
|
return fmt.Errorf("failed to cancel schedule: %s", resp.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := WebSocketCloseConnection(username, 1000, "Navidrome disconnect"); err != nil {
|
if resp, err := WebSocketCloseConnection(username, 1000, "Navidrome disconnect"); err != nil {
|
||||||
return fmt.Errorf("failed to close WebSocket connection: %w", err)
|
return fmt.Errorf("failed to close WebSocket connection: %w", err)
|
||||||
|
} else if resp.Error != "" {
|
||||||
|
return fmt.Errorf("failed to close WebSocket connection: %s", resp.Error)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -325,8 +337,10 @@ func handleWebSocketMessage(connectionID, message string) error {
|
|||||||
if v := msg["s"]; v != nil {
|
if v := msg["s"]; v != nil {
|
||||||
seq := int64(v.(float64))
|
seq := int64(v.(float64))
|
||||||
pdk.Log(pdk.LogTrace, fmt.Sprintf("Received sequence number for connection '%s': %d", connectionID, seq))
|
pdk.Log(pdk.LogTrace, fmt.Sprintf("Received sequence number for connection '%s': %d", connectionID, seq))
|
||||||
if err := CacheSetInt(fmt.Sprintf("discord.seq.%s", connectionID), seq, int64(heartbeatInterval*2)); err != nil {
|
if resp, err := CacheSetInt(fmt.Sprintf("discord.seq.%s", connectionID), seq, int64(heartbeatInterval*2)); err != nil {
|
||||||
return fmt.Errorf("failed to store sequence number for user %s: %w", connectionID, err)
|
return fmt.Errorf("failed to store sequence number for user %s: %w", connectionID, err)
|
||||||
|
} else if resp.Error != "" {
|
||||||
|
return fmt.Errorf("failed to store sequence number for user %s: %s", connectionID, resp.Error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -9,24 +9,48 @@ import (
|
|||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ArtworkGetArtistUrlRequest is the request type for Artwork.GetArtistUrl.
|
||||||
|
type ArtworkGetArtistUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetArtistUrlResponse is the response type for Artwork.GetArtistUrl.
|
// ArtworkGetArtistUrlResponse is the response type for Artwork.GetArtistUrl.
|
||||||
type ArtworkGetArtistUrlResponse struct {
|
type ArtworkGetArtistUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetAlbumUrlRequest is the request type for Artwork.GetAlbumUrl.
|
||||||
|
type ArtworkGetAlbumUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetAlbumUrlResponse is the response type for Artwork.GetAlbumUrl.
|
// ArtworkGetAlbumUrlResponse is the response type for Artwork.GetAlbumUrl.
|
||||||
type ArtworkGetAlbumUrlResponse struct {
|
type ArtworkGetAlbumUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetTrackUrlRequest is the request type for Artwork.GetTrackUrl.
|
||||||
|
type ArtworkGetTrackUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetTrackUrlResponse is the response type for Artwork.GetTrackUrl.
|
// ArtworkGetTrackUrlResponse is the response type for Artwork.GetTrackUrl.
|
||||||
type ArtworkGetTrackUrlResponse struct {
|
type ArtworkGetTrackUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetPlaylistUrlRequest is the request type for Artwork.GetPlaylistUrl.
|
||||||
|
type ArtworkGetPlaylistUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetPlaylistUrlResponse is the response type for Artwork.GetPlaylistUrl.
|
// ArtworkGetPlaylistUrlResponse is the response type for Artwork.GetPlaylistUrl.
|
||||||
type ArtworkGetPlaylistUrlResponse struct {
|
type ArtworkGetPlaylistUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
@ -48,26 +72,32 @@ func newArtworkGetArtistUrlHostFunction(service ArtworkService) extism.HostFunct
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"artwork_getartisturl",
|
"artwork_getartisturl",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
id, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
size := extism.DecodeI32(stack[1])
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
url, err := service.GetArtistUrl(ctx, id, size)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
artworkWriteError(p, stack, err)
|
artworkWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req ArtworkGetArtistUrlRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
artworkWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
url, svcErr := service.GetArtistUrl(ctx, req.Id, req.Size)
|
||||||
|
if svcErr != nil {
|
||||||
|
artworkWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := ArtworkGetArtistUrlResponse{
|
resp := ArtworkGetArtistUrlResponse{
|
||||||
Url: url,
|
Url: url,
|
||||||
}
|
}
|
||||||
artworkWriteResponse(p, stack, resp)
|
artworkWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypeI32},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -76,26 +106,32 @@ func newArtworkGetAlbumUrlHostFunction(service ArtworkService) extism.HostFuncti
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"artwork_getalbumurl",
|
"artwork_getalbumurl",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
id, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
size := extism.DecodeI32(stack[1])
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
url, err := service.GetAlbumUrl(ctx, id, size)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
artworkWriteError(p, stack, err)
|
artworkWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req ArtworkGetAlbumUrlRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
artworkWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
url, svcErr := service.GetAlbumUrl(ctx, req.Id, req.Size)
|
||||||
|
if svcErr != nil {
|
||||||
|
artworkWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := ArtworkGetAlbumUrlResponse{
|
resp := ArtworkGetAlbumUrlResponse{
|
||||||
Url: url,
|
Url: url,
|
||||||
}
|
}
|
||||||
artworkWriteResponse(p, stack, resp)
|
artworkWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypeI32},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -104,26 +140,32 @@ func newArtworkGetTrackUrlHostFunction(service ArtworkService) extism.HostFuncti
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"artwork_gettrackurl",
|
"artwork_gettrackurl",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
id, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
size := extism.DecodeI32(stack[1])
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
url, err := service.GetTrackUrl(ctx, id, size)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
artworkWriteError(p, stack, err)
|
artworkWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req ArtworkGetTrackUrlRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
artworkWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
url, svcErr := service.GetTrackUrl(ctx, req.Id, req.Size)
|
||||||
|
if svcErr != nil {
|
||||||
|
artworkWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := ArtworkGetTrackUrlResponse{
|
resp := ArtworkGetTrackUrlResponse{
|
||||||
Url: url,
|
Url: url,
|
||||||
}
|
}
|
||||||
artworkWriteResponse(p, stack, resp)
|
artworkWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypeI32},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -132,26 +174,32 @@ func newArtworkGetPlaylistUrlHostFunction(service ArtworkService) extism.HostFun
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"artwork_getplaylisturl",
|
"artwork_getplaylisturl",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
id, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
size := extism.DecodeI32(stack[1])
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
url, err := service.GetPlaylistUrl(ctx, id, size)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
artworkWriteError(p, stack, err)
|
artworkWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req ArtworkGetPlaylistUrlRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
artworkWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
url, svcErr := service.GetPlaylistUrl(ctx, req.Id, req.Size)
|
||||||
|
if svcErr != nil {
|
||||||
|
artworkWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := ArtworkGetPlaylistUrlResponse{
|
resp := ArtworkGetPlaylistUrlResponse{
|
||||||
Url: url,
|
Url: url,
|
||||||
}
|
}
|
||||||
artworkWriteResponse(p, stack, resp)
|
artworkWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypeI32},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,23 @@ import (
|
|||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CacheSetStringRequest is the request type for Cache.SetString.
|
||||||
|
type CacheSetStringRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetStringResponse is the response type for Cache.SetString.
|
||||||
|
type CacheSetStringResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetStringRequest is the request type for Cache.GetString.
|
||||||
|
type CacheGetStringRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetStringResponse is the response type for Cache.GetString.
|
// CacheGetStringResponse is the response type for Cache.GetString.
|
||||||
type CacheGetStringResponse struct {
|
type CacheGetStringResponse struct {
|
||||||
Value string `json:"value,omitempty"`
|
Value string `json:"value,omitempty"`
|
||||||
@ -16,6 +33,23 @@ type CacheGetStringResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetIntRequest is the request type for Cache.SetInt.
|
||||||
|
type CacheSetIntRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value int64 `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetIntResponse is the response type for Cache.SetInt.
|
||||||
|
type CacheSetIntResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetIntRequest is the request type for Cache.GetInt.
|
||||||
|
type CacheGetIntRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetIntResponse is the response type for Cache.GetInt.
|
// CacheGetIntResponse is the response type for Cache.GetInt.
|
||||||
type CacheGetIntResponse struct {
|
type CacheGetIntResponse struct {
|
||||||
Value int64 `json:"value,omitempty"`
|
Value int64 `json:"value,omitempty"`
|
||||||
@ -23,6 +57,23 @@ type CacheGetIntResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetFloatRequest is the request type for Cache.SetFloat.
|
||||||
|
type CacheSetFloatRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetFloatResponse is the response type for Cache.SetFloat.
|
||||||
|
type CacheSetFloatResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetFloatRequest is the request type for Cache.GetFloat.
|
||||||
|
type CacheGetFloatRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetFloatResponse is the response type for Cache.GetFloat.
|
// CacheGetFloatResponse is the response type for Cache.GetFloat.
|
||||||
type CacheGetFloatResponse struct {
|
type CacheGetFloatResponse struct {
|
||||||
Value float64 `json:"value,omitempty"`
|
Value float64 `json:"value,omitempty"`
|
||||||
@ -30,6 +81,23 @@ type CacheGetFloatResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetBytesRequest is the request type for Cache.SetBytes.
|
||||||
|
type CacheSetBytesRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value []byte `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetBytesResponse is the response type for Cache.SetBytes.
|
||||||
|
type CacheSetBytesResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetBytesRequest is the request type for Cache.GetBytes.
|
||||||
|
type CacheGetBytesRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetBytesResponse is the response type for Cache.GetBytes.
|
// CacheGetBytesResponse is the response type for Cache.GetBytes.
|
||||||
type CacheGetBytesResponse struct {
|
type CacheGetBytesResponse struct {
|
||||||
Value []byte `json:"value,omitempty"`
|
Value []byte `json:"value,omitempty"`
|
||||||
@ -37,12 +105,27 @@ type CacheGetBytesResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheHasRequest is the request type for Cache.Has.
|
||||||
|
type CacheHasRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheHasResponse is the response type for Cache.Has.
|
// CacheHasResponse is the response type for Cache.Has.
|
||||||
type CacheHasResponse struct {
|
type CacheHasResponse struct {
|
||||||
Exists bool `json:"exists,omitempty"`
|
Exists bool `json:"exists,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheRemoveRequest is the request type for Cache.Remove.
|
||||||
|
type CacheRemoveRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheRemoveResponse is the response type for Cache.Remove.
|
||||||
|
type CacheRemoveResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterCacheHostFunctions registers Cache service host functions.
|
// RegisterCacheHostFunctions registers Cache service host functions.
|
||||||
// The returned host functions should be added to the plugin's configuration.
|
// The returned host functions should be added to the plugin's configuration.
|
||||||
func RegisterCacheHostFunctions(service CacheService) []extism.HostFunction {
|
func RegisterCacheHostFunctions(service CacheService) []extism.HostFunction {
|
||||||
@ -64,32 +147,29 @@ func newCacheSetStringHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_setstring",
|
"cache_setstring",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value, err := p.ReadString(stack[1])
|
var req CacheSetStringRequest
|
||||||
if err != nil {
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ttlSeconds := int64(stack[2])
|
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.SetString(ctx, key, value, ttlSeconds)
|
if svcErr := service.SetString(ctx, req.Key, req.Value, req.TtlSeconds); svcErr != nil {
|
||||||
if err != nil {
|
cacheWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := CacheSetStringResponse{}
|
||||||
}
|
cacheWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypePTR, extism.ValueTypeI64},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -98,18 +178,25 @@ func newCacheGetStringHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_getstring",
|
"cache_getstring",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
value, exists, err := service.GetString(ctx, key)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cacheWriteError(p, stack, err)
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req CacheGetStringRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
value, exists, svcErr := service.GetString(ctx, req.Key)
|
||||||
|
if svcErr != nil {
|
||||||
|
cacheWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := CacheGetStringResponse{
|
resp := CacheGetStringResponse{
|
||||||
Value: value,
|
Value: value,
|
||||||
@ -126,29 +213,29 @@ func newCacheSetIntHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_setint",
|
"cache_setint",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req CacheSetIntRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value := int64(stack[1])
|
|
||||||
ttlSeconds := int64(stack[2])
|
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.SetInt(ctx, key, value, ttlSeconds)
|
if svcErr := service.SetInt(ctx, req.Key, req.Value, req.TtlSeconds); svcErr != nil {
|
||||||
if err != nil {
|
cacheWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := CacheSetIntResponse{}
|
||||||
}
|
cacheWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypeI64, extism.ValueTypeI64},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -157,18 +244,25 @@ func newCacheGetIntHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_getint",
|
"cache_getint",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
value, exists, err := service.GetInt(ctx, key)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cacheWriteError(p, stack, err)
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req CacheGetIntRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
value, exists, svcErr := service.GetInt(ctx, req.Key)
|
||||||
|
if svcErr != nil {
|
||||||
|
cacheWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := CacheGetIntResponse{
|
resp := CacheGetIntResponse{
|
||||||
Value: value,
|
Value: value,
|
||||||
@ -185,29 +279,29 @@ func newCacheSetFloatHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_setfloat",
|
"cache_setfloat",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req CacheSetFloatRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value := extism.DecodeF64(stack[1])
|
|
||||||
ttlSeconds := int64(stack[2])
|
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.SetFloat(ctx, key, value, ttlSeconds)
|
if svcErr := service.SetFloat(ctx, req.Key, req.Value, req.TtlSeconds); svcErr != nil {
|
||||||
if err != nil {
|
cacheWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := CacheSetFloatResponse{}
|
||||||
}
|
cacheWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypeF64, extism.ValueTypeI64},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -216,18 +310,25 @@ func newCacheGetFloatHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_getfloat",
|
"cache_getfloat",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
value, exists, err := service.GetFloat(ctx, key)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cacheWriteError(p, stack, err)
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req CacheGetFloatRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
value, exists, svcErr := service.GetFloat(ctx, req.Key)
|
||||||
|
if svcErr != nil {
|
||||||
|
cacheWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := CacheGetFloatResponse{
|
resp := CacheGetFloatResponse{
|
||||||
Value: value,
|
Value: value,
|
||||||
@ -244,32 +345,29 @@ func newCacheSetBytesHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_setbytes",
|
"cache_setbytes",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value, err := p.ReadBytes(stack[1])
|
var req CacheSetBytesRequest
|
||||||
if err != nil {
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ttlSeconds := int64(stack[2])
|
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.SetBytes(ctx, key, value, ttlSeconds)
|
if svcErr := service.SetBytes(ctx, req.Key, req.Value, req.TtlSeconds); svcErr != nil {
|
||||||
if err != nil {
|
cacheWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := CacheSetBytesResponse{}
|
||||||
}
|
cacheWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypePTR, extism.ValueTypeI64},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -278,18 +376,25 @@ func newCacheGetBytesHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_getbytes",
|
"cache_getbytes",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
value, exists, err := service.GetBytes(ctx, key)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cacheWriteError(p, stack, err)
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req CacheGetBytesRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
value, exists, svcErr := service.GetBytes(ctx, req.Key)
|
||||||
|
if svcErr != nil {
|
||||||
|
cacheWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := CacheGetBytesResponse{
|
resp := CacheGetBytesResponse{
|
||||||
Value: value,
|
Value: value,
|
||||||
@ -306,18 +411,25 @@ func newCacheHasHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_has",
|
"cache_has",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
exists, err := service.Has(ctx, key)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cacheWriteError(p, stack, err)
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req CacheHasRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
exists, svcErr := service.Has(ctx, req.Key)
|
||||||
|
if svcErr != nil {
|
||||||
|
cacheWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := CacheHasResponse{
|
resp := CacheHasResponse{
|
||||||
Exists: exists,
|
Exists: exists,
|
||||||
@ -333,25 +445,27 @@ func newCacheRemoveHostFunction(service CacheService) extism.HostFunction {
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"cache_remove",
|
"cache_remove",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
key, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req CacheRemoveRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
cacheWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.Remove(ctx, key)
|
if svcErr := service.Remove(ctx, req.Key); svcErr != nil {
|
||||||
if err != nil {
|
cacheWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := CacheRemoveResponse{}
|
||||||
}
|
cacheWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
|
|||||||
@ -16,22 +16,28 @@ import (
|
|||||||
// artwork_getartisturl is the host function provided by Navidrome.
|
// artwork_getartisturl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_getartisturl
|
//go:wasmimport extism:host/user artwork_getartisturl
|
||||||
func artwork_getartisturl(uint64, int32) uint64
|
func artwork_getartisturl(uint64) uint64
|
||||||
|
|
||||||
// artwork_getalbumurl is the host function provided by Navidrome.
|
// artwork_getalbumurl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_getalbumurl
|
//go:wasmimport extism:host/user artwork_getalbumurl
|
||||||
func artwork_getalbumurl(uint64, int32) uint64
|
func artwork_getalbumurl(uint64) uint64
|
||||||
|
|
||||||
// artwork_gettrackurl is the host function provided by Navidrome.
|
// artwork_gettrackurl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_gettrackurl
|
//go:wasmimport extism:host/user artwork_gettrackurl
|
||||||
func artwork_gettrackurl(uint64, int32) uint64
|
func artwork_gettrackurl(uint64) uint64
|
||||||
|
|
||||||
// artwork_getplaylisturl is the host function provided by Navidrome.
|
// artwork_getplaylisturl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_getplaylisturl
|
//go:wasmimport extism:host/user artwork_getplaylisturl
|
||||||
func artwork_getplaylisturl(uint64, int32) uint64
|
func artwork_getplaylisturl(uint64) uint64
|
||||||
|
|
||||||
|
// ArtworkGetArtistUrlRequest is the request type for Artwork.GetArtistUrl.
|
||||||
|
type ArtworkGetArtistUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetArtistUrlResponse is the response type for Artwork.GetArtistUrl.
|
// ArtworkGetArtistUrlResponse is the response type for Artwork.GetArtistUrl.
|
||||||
type ArtworkGetArtistUrlResponse struct {
|
type ArtworkGetArtistUrlResponse struct {
|
||||||
@ -39,18 +45,36 @@ type ArtworkGetArtistUrlResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetAlbumUrlRequest is the request type for Artwork.GetAlbumUrl.
|
||||||
|
type ArtworkGetAlbumUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetAlbumUrlResponse is the response type for Artwork.GetAlbumUrl.
|
// ArtworkGetAlbumUrlResponse is the response type for Artwork.GetAlbumUrl.
|
||||||
type ArtworkGetAlbumUrlResponse struct {
|
type ArtworkGetAlbumUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetTrackUrlRequest is the request type for Artwork.GetTrackUrl.
|
||||||
|
type ArtworkGetTrackUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetTrackUrlResponse is the response type for Artwork.GetTrackUrl.
|
// ArtworkGetTrackUrlResponse is the response type for Artwork.GetTrackUrl.
|
||||||
type ArtworkGetTrackUrlResponse struct {
|
type ArtworkGetTrackUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetPlaylistUrlRequest is the request type for Artwork.GetPlaylistUrl.
|
||||||
|
type ArtworkGetPlaylistUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetPlaylistUrlResponse is the response type for Artwork.GetPlaylistUrl.
|
// ArtworkGetPlaylistUrlResponse is the response type for Artwork.GetPlaylistUrl.
|
||||||
type ArtworkGetPlaylistUrlResponse struct {
|
type ArtworkGetPlaylistUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
@ -66,11 +90,20 @@ type ArtworkGetPlaylistUrlResponse struct {
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetArtistUrl(id string, size int32) (*ArtworkGetArtistUrlResponse, error) {
|
func ArtworkGetArtistUrl(id string, size int32) (*ArtworkGetArtistUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetArtistUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_getartisturl(idMem.Offset(), size)
|
responsePtr := artwork_getartisturl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -94,11 +127,20 @@ func ArtworkGetArtistUrl(id string, size int32) (*ArtworkGetArtistUrlResponse, e
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetAlbumUrl(id string, size int32) (*ArtworkGetAlbumUrlResponse, error) {
|
func ArtworkGetAlbumUrl(id string, size int32) (*ArtworkGetAlbumUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetAlbumUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_getalbumurl(idMem.Offset(), size)
|
responsePtr := artwork_getalbumurl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -122,11 +164,20 @@ func ArtworkGetAlbumUrl(id string, size int32) (*ArtworkGetAlbumUrlResponse, err
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetTrackUrl(id string, size int32) (*ArtworkGetTrackUrlResponse, error) {
|
func ArtworkGetTrackUrl(id string, size int32) (*ArtworkGetTrackUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetTrackUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_gettrackurl(idMem.Offset(), size)
|
responsePtr := artwork_gettrackurl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -150,11 +201,20 @@ func ArtworkGetTrackUrl(id string, size int32) (*ArtworkGetTrackUrlResponse, err
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetPlaylistUrl(id string, size int32) (*ArtworkGetPlaylistUrlResponse, error) {
|
func ArtworkGetPlaylistUrl(id string, size int32) (*ArtworkGetPlaylistUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetPlaylistUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_getplaylisturl(idMem.Offset(), size)
|
responsePtr := artwork_getplaylisturl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
@ -9,7 +9,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -17,7 +16,7 @@ import (
|
|||||||
// cache_setstring is the host function provided by Navidrome.
|
// cache_setstring is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setstring
|
//go:wasmimport extism:host/user cache_setstring
|
||||||
func cache_setstring(uint64, uint64, int64) uint64
|
func cache_setstring(uint64) uint64
|
||||||
|
|
||||||
// cache_getstring is the host function provided by Navidrome.
|
// cache_getstring is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -27,7 +26,7 @@ func cache_getstring(uint64) uint64
|
|||||||
// cache_setint is the host function provided by Navidrome.
|
// cache_setint is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setint
|
//go:wasmimport extism:host/user cache_setint
|
||||||
func cache_setint(uint64, int64, int64) uint64
|
func cache_setint(uint64) uint64
|
||||||
|
|
||||||
// cache_getint is the host function provided by Navidrome.
|
// cache_getint is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -37,7 +36,7 @@ func cache_getint(uint64) uint64
|
|||||||
// cache_setfloat is the host function provided by Navidrome.
|
// cache_setfloat is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setfloat
|
//go:wasmimport extism:host/user cache_setfloat
|
||||||
func cache_setfloat(uint64, float64, int64) uint64
|
func cache_setfloat(uint64) uint64
|
||||||
|
|
||||||
// cache_getfloat is the host function provided by Navidrome.
|
// cache_getfloat is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -47,7 +46,7 @@ func cache_getfloat(uint64) uint64
|
|||||||
// cache_setbytes is the host function provided by Navidrome.
|
// cache_setbytes is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setbytes
|
//go:wasmimport extism:host/user cache_setbytes
|
||||||
func cache_setbytes(uint64, uint64, int64) uint64
|
func cache_setbytes(uint64) uint64
|
||||||
|
|
||||||
// cache_getbytes is the host function provided by Navidrome.
|
// cache_getbytes is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -64,6 +63,23 @@ func cache_has(uint64) uint64
|
|||||||
//go:wasmimport extism:host/user cache_remove
|
//go:wasmimport extism:host/user cache_remove
|
||||||
func cache_remove(uint64) uint64
|
func cache_remove(uint64) uint64
|
||||||
|
|
||||||
|
// CacheSetStringRequest is the request type for Cache.SetString.
|
||||||
|
type CacheSetStringRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetStringResponse is the response type for Cache.SetString.
|
||||||
|
type CacheSetStringResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetStringRequest is the request type for Cache.GetString.
|
||||||
|
type CacheGetStringRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetStringResponse is the response type for Cache.GetString.
|
// CacheGetStringResponse is the response type for Cache.GetString.
|
||||||
type CacheGetStringResponse struct {
|
type CacheGetStringResponse struct {
|
||||||
Value string `json:"value,omitempty"`
|
Value string `json:"value,omitempty"`
|
||||||
@ -71,6 +87,23 @@ type CacheGetStringResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetIntRequest is the request type for Cache.SetInt.
|
||||||
|
type CacheSetIntRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value int64 `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetIntResponse is the response type for Cache.SetInt.
|
||||||
|
type CacheSetIntResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetIntRequest is the request type for Cache.GetInt.
|
||||||
|
type CacheGetIntRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetIntResponse is the response type for Cache.GetInt.
|
// CacheGetIntResponse is the response type for Cache.GetInt.
|
||||||
type CacheGetIntResponse struct {
|
type CacheGetIntResponse struct {
|
||||||
Value int64 `json:"value,omitempty"`
|
Value int64 `json:"value,omitempty"`
|
||||||
@ -78,6 +111,23 @@ type CacheGetIntResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetFloatRequest is the request type for Cache.SetFloat.
|
||||||
|
type CacheSetFloatRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetFloatResponse is the response type for Cache.SetFloat.
|
||||||
|
type CacheSetFloatResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetFloatRequest is the request type for Cache.GetFloat.
|
||||||
|
type CacheGetFloatRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetFloatResponse is the response type for Cache.GetFloat.
|
// CacheGetFloatResponse is the response type for Cache.GetFloat.
|
||||||
type CacheGetFloatResponse struct {
|
type CacheGetFloatResponse struct {
|
||||||
Value float64 `json:"value,omitempty"`
|
Value float64 `json:"value,omitempty"`
|
||||||
@ -85,6 +135,23 @@ type CacheGetFloatResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetBytesRequest is the request type for Cache.SetBytes.
|
||||||
|
type CacheSetBytesRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value []byte `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetBytesResponse is the response type for Cache.SetBytes.
|
||||||
|
type CacheSetBytesResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetBytesRequest is the request type for Cache.GetBytes.
|
||||||
|
type CacheGetBytesRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetBytesResponse is the response type for Cache.GetBytes.
|
// CacheGetBytesResponse is the response type for Cache.GetBytes.
|
||||||
type CacheGetBytesResponse struct {
|
type CacheGetBytesResponse struct {
|
||||||
Value []byte `json:"value,omitempty"`
|
Value []byte `json:"value,omitempty"`
|
||||||
@ -92,12 +159,27 @@ type CacheGetBytesResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheHasRequest is the request type for Cache.Has.
|
||||||
|
type CacheHasRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheHasResponse is the response type for Cache.Has.
|
// CacheHasResponse is the response type for Cache.Has.
|
||||||
type CacheHasResponse struct {
|
type CacheHasResponse struct {
|
||||||
Exists bool `json:"exists,omitempty"`
|
Exists bool `json:"exists,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheRemoveRequest is the request type for Cache.Remove.
|
||||||
|
type CacheRemoveRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheRemoveResponse is the response type for Cache.Remove.
|
||||||
|
type CacheRemoveResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheSetString calls the cache_setstring host function.
|
// CacheSetString calls the cache_setstring host function.
|
||||||
// SetString stores a string value in the cache.
|
// SetString stores a string value in the cache.
|
||||||
//
|
//
|
||||||
@ -107,24 +189,34 @@ type CacheHasResponse struct {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetString(key string, value string, ttlSeconds int64) error {
|
func CacheSetString(key string, value string, ttlSeconds int64) (*CacheSetStringResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetStringRequest{
|
||||||
valueMem := pdk.AllocateString(value)
|
Key: key,
|
||||||
defer valueMem.Free()
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setstring(keyMem.Offset(), valueMem.Offset(), ttlSeconds)
|
responsePtr := cache_setstring(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetStringResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetString calls the cache_getstring host function.
|
// CacheGetString calls the cache_getstring host function.
|
||||||
@ -136,11 +228,19 @@ func CacheSetString(key string, value string, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not a string, exists will be false.
|
// or the stored value is not a string, exists will be false.
|
||||||
func CacheGetString(key string) (*CacheGetStringResponse, error) {
|
func CacheGetString(key string) (*CacheGetStringResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetStringRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getstring(keyMem.Offset())
|
responsePtr := cache_getstring(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -164,22 +264,34 @@ func CacheGetString(key string) (*CacheGetStringResponse, error) {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetInt(key string, value int64, ttlSeconds int64) error {
|
func CacheSetInt(key string, value int64, ttlSeconds int64) (*CacheSetIntResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetIntRequest{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setint(keyMem.Offset(), value, ttlSeconds)
|
responsePtr := cache_setint(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetIntResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetInt calls the cache_getint host function.
|
// CacheGetInt calls the cache_getint host function.
|
||||||
@ -191,11 +303,19 @@ func CacheSetInt(key string, value int64, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not an integer, exists will be false.
|
// or the stored value is not an integer, exists will be false.
|
||||||
func CacheGetInt(key string) (*CacheGetIntResponse, error) {
|
func CacheGetInt(key string) (*CacheGetIntResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetIntRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getint(keyMem.Offset())
|
responsePtr := cache_getint(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -219,22 +339,34 @@ func CacheGetInt(key string) (*CacheGetIntResponse, error) {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetFloat(key string, value float64, ttlSeconds int64) error {
|
func CacheSetFloat(key string, value float64, ttlSeconds int64) (*CacheSetFloatResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetFloatRequest{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setfloat(keyMem.Offset(), value, ttlSeconds)
|
responsePtr := cache_setfloat(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetFloatResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetFloat calls the cache_getfloat host function.
|
// CacheGetFloat calls the cache_getfloat host function.
|
||||||
@ -246,11 +378,19 @@ func CacheSetFloat(key string, value float64, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not a float, exists will be false.
|
// or the stored value is not a float, exists will be false.
|
||||||
func CacheGetFloat(key string) (*CacheGetFloatResponse, error) {
|
func CacheGetFloat(key string) (*CacheGetFloatResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetFloatRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getfloat(keyMem.Offset())
|
responsePtr := cache_getfloat(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -274,24 +414,34 @@ func CacheGetFloat(key string) (*CacheGetFloatResponse, error) {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetBytes(key string, value []byte, ttlSeconds int64) error {
|
func CacheSetBytes(key string, value []byte, ttlSeconds int64) (*CacheSetBytesResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetBytesRequest{
|
||||||
valueMem := pdk.AllocateBytes(value)
|
Key: key,
|
||||||
defer valueMem.Free()
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setbytes(keyMem.Offset(), valueMem.Offset(), ttlSeconds)
|
responsePtr := cache_setbytes(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetBytesResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetBytes calls the cache_getbytes host function.
|
// CacheGetBytes calls the cache_getbytes host function.
|
||||||
@ -303,11 +453,19 @@ func CacheSetBytes(key string, value []byte, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not a byte slice, exists will be false.
|
// or the stored value is not a byte slice, exists will be false.
|
||||||
func CacheGetBytes(key string) (*CacheGetBytesResponse, error) {
|
func CacheGetBytes(key string) (*CacheGetBytesResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetBytesRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getbytes(keyMem.Offset())
|
responsePtr := cache_getbytes(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -330,11 +488,19 @@ func CacheGetBytes(key string) (*CacheGetBytesResponse, error) {
|
|||||||
//
|
//
|
||||||
// Returns true if the key exists and has not expired.
|
// Returns true if the key exists and has not expired.
|
||||||
func CacheHas(key string) (*CacheHasResponse, error) {
|
func CacheHas(key string) (*CacheHasResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheHasRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_has(keyMem.Offset())
|
responsePtr := cache_has(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -356,20 +522,30 @@ func CacheHas(key string) (*CacheHasResponse, error) {
|
|||||||
// - key: The cache key (will be namespaced with plugin ID)
|
// - key: The cache key (will be namespaced with plugin ID)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails. Does not return an error if the key doesn't exist.
|
// Returns an error if the operation fails. Does not return an error if the key doesn't exist.
|
||||||
func CacheRemove(key string) error {
|
func CacheRemove(key string) (*CacheRemoveResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheRemoveRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_remove(keyMem.Offset())
|
responsePtr := cache_remove(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheRemoveResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -17,30 +16,54 @@ import (
|
|||||||
// scheduler_scheduleonetime is the host function provided by Navidrome.
|
// scheduler_scheduleonetime is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user scheduler_scheduleonetime
|
//go:wasmimport extism:host/user scheduler_scheduleonetime
|
||||||
func scheduler_scheduleonetime(int32, uint64, uint64) uint64
|
func scheduler_scheduleonetime(uint64) uint64
|
||||||
|
|
||||||
// scheduler_schedulerecurring is the host function provided by Navidrome.
|
// scheduler_schedulerecurring is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user scheduler_schedulerecurring
|
//go:wasmimport extism:host/user scheduler_schedulerecurring
|
||||||
func scheduler_schedulerecurring(uint64, uint64, uint64) uint64
|
func scheduler_schedulerecurring(uint64) uint64
|
||||||
|
|
||||||
// scheduler_cancelschedule is the host function provided by Navidrome.
|
// scheduler_cancelschedule is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user scheduler_cancelschedule
|
//go:wasmimport extism:host/user scheduler_cancelschedule
|
||||||
func scheduler_cancelschedule(uint64) uint64
|
func scheduler_cancelschedule(uint64) uint64
|
||||||
|
|
||||||
|
// SchedulerScheduleOneTimeRequest is the request type for Scheduler.ScheduleOneTime.
|
||||||
|
type SchedulerScheduleOneTimeRequest struct {
|
||||||
|
DelaySeconds int32 `json:"delaySeconds"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
||||||
type SchedulerScheduleOneTimeResponse struct {
|
type SchedulerScheduleOneTimeResponse struct {
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulerScheduleRecurringRequest is the request type for Scheduler.ScheduleRecurring.
|
||||||
|
type SchedulerScheduleRecurringRequest struct {
|
||||||
|
CronExpression string `json:"cronExpression"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
||||||
type SchedulerScheduleRecurringResponse struct {
|
type SchedulerScheduleRecurringResponse struct {
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleRequest is the request type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleRequest struct {
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleResponse is the response type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleOneTime calls the scheduler_scheduleonetime host function.
|
// SchedulerScheduleOneTime calls the scheduler_scheduleonetime host function.
|
||||||
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
|
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
|
||||||
// Plugins that use this function must also implement the SchedulerCallback capability
|
// Plugins that use this function must also implement the SchedulerCallback capability
|
||||||
@ -52,13 +75,21 @@ type SchedulerScheduleRecurringResponse struct {
|
|||||||
//
|
//
|
||||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||||
func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID string) (*SchedulerScheduleOneTimeResponse, error) {
|
func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID string) (*SchedulerScheduleOneTimeResponse, error) {
|
||||||
payloadMem := pdk.AllocateString(payload)
|
// Marshal request to JSON
|
||||||
defer payloadMem.Free()
|
req := SchedulerScheduleOneTimeRequest{
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
DelaySeconds: delaySeconds,
|
||||||
defer scheduleIDMem.Free()
|
Payload: payload,
|
||||||
|
ScheduleID: scheduleID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := scheduler_scheduleonetime(delaySeconds, payloadMem.Offset(), scheduleIDMem.Offset())
|
responsePtr := scheduler_scheduleonetime(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -84,15 +115,21 @@ func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID str
|
|||||||
//
|
//
|
||||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||||
func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleID string) (*SchedulerScheduleRecurringResponse, error) {
|
func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleID string) (*SchedulerScheduleRecurringResponse, error) {
|
||||||
cronExpressionMem := pdk.AllocateString(cronExpression)
|
// Marshal request to JSON
|
||||||
defer cronExpressionMem.Free()
|
req := SchedulerScheduleRecurringRequest{
|
||||||
payloadMem := pdk.AllocateString(payload)
|
CronExpression: cronExpression,
|
||||||
defer payloadMem.Free()
|
Payload: payload,
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
ScheduleID: scheduleID,
|
||||||
defer scheduleIDMem.Free()
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := scheduler_schedulerecurring(cronExpressionMem.Offset(), payloadMem.Offset(), scheduleIDMem.Offset())
|
responsePtr := scheduler_schedulerecurring(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -114,20 +151,30 @@ func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleI
|
|||||||
// any future events.
|
// any future events.
|
||||||
//
|
//
|
||||||
// Returns an error if the schedule ID is not found or if cancellation fails.
|
// Returns an error if the schedule ID is not found or if cancellation fails.
|
||||||
func SchedulerCancelSchedule(scheduleID string) error {
|
func SchedulerCancelSchedule(scheduleID string) (*SchedulerCancelScheduleResponse, error) {
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
// Marshal request to JSON
|
||||||
defer scheduleIDMem.Free()
|
req := SchedulerCancelScheduleRequest{
|
||||||
|
ScheduleID: scheduleID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := scheduler_cancelschedule(scheduleIDMem.Offset())
|
responsePtr := scheduler_cancelschedule(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response SchedulerCancelScheduleResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,11 @@ import (
|
|||||||
//go:wasmimport extism:host/user subsonicapi_call
|
//go:wasmimport extism:host/user subsonicapi_call
|
||||||
func subsonicapi_call(uint64) uint64
|
func subsonicapi_call(uint64) uint64
|
||||||
|
|
||||||
|
// SubsonicAPICallRequest is the request type for SubsonicAPI.Call.
|
||||||
|
type SubsonicAPICallRequest struct {
|
||||||
|
Uri string `json:"uri"`
|
||||||
|
}
|
||||||
|
|
||||||
// SubsonicAPICallResponse is the response type for SubsonicAPI.Call.
|
// SubsonicAPICallResponse is the response type for SubsonicAPI.Call.
|
||||||
type SubsonicAPICallResponse struct {
|
type SubsonicAPICallResponse struct {
|
||||||
ResponseJSON string `json:"responseJSON,omitempty"`
|
ResponseJSON string `json:"responseJSON,omitempty"`
|
||||||
@ -30,11 +35,19 @@ type SubsonicAPICallResponse struct {
|
|||||||
// The uri parameter should be the Subsonic API path without the server prefix,
|
// The uri parameter should be the Subsonic API path without the server prefix,
|
||||||
// e.g., "getAlbumList2?type=random&size=10". The response is returned as raw JSON.
|
// e.g., "getAlbumList2?type=random&size=10". The response is returned as raw JSON.
|
||||||
func SubsonicAPICall(uri string) (*SubsonicAPICallResponse, error) {
|
func SubsonicAPICall(uri string) (*SubsonicAPICallResponse, error) {
|
||||||
uriMem := pdk.AllocateString(uri)
|
// Marshal request to JSON
|
||||||
defer uriMem.Free()
|
req := SubsonicAPICallRequest{
|
||||||
|
Uri: uri,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := subsonicapi_call(uriMem.Offset())
|
responsePtr := subsonicapi_call(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
@ -9,13 +9,11 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
// websocket_connect is the host function provided by Navidrome.
|
// websocket_connect is the host function provided by Navidrome.
|
||||||
// Takes a single JSON request pointer containing url, headers, and connectionID.
|
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user websocket_connect
|
//go:wasmimport extism:host/user websocket_connect
|
||||||
func websocket_connect(uint64) uint64
|
func websocket_connect(uint64) uint64
|
||||||
@ -23,17 +21,17 @@ func websocket_connect(uint64) uint64
|
|||||||
// websocket_sendtext is the host function provided by Navidrome.
|
// websocket_sendtext is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user websocket_sendtext
|
//go:wasmimport extism:host/user websocket_sendtext
|
||||||
func websocket_sendtext(uint64, uint64) uint64
|
func websocket_sendtext(uint64) uint64
|
||||||
|
|
||||||
// websocket_sendbinary is the host function provided by Navidrome.
|
// websocket_sendbinary is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user websocket_sendbinary
|
//go:wasmimport extism:host/user websocket_sendbinary
|
||||||
func websocket_sendbinary(uint64, uint64) uint64
|
func websocket_sendbinary(uint64) uint64
|
||||||
|
|
||||||
// websocket_closeconnection is the host function provided by Navidrome.
|
// websocket_closeconnection is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user websocket_closeconnection
|
//go:wasmimport extism:host/user websocket_closeconnection
|
||||||
func websocket_closeconnection(uint64, int32, uint64) uint64
|
func websocket_closeconnection(uint64) uint64
|
||||||
|
|
||||||
// WebSocketConnectRequest is the request type for WebSocket.Connect.
|
// WebSocketConnectRequest is the request type for WebSocket.Connect.
|
||||||
type WebSocketConnectRequest struct {
|
type WebSocketConnectRequest struct {
|
||||||
@ -48,6 +46,40 @@ type WebSocketConnectResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextRequest is the request type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextResponse is the response type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryRequest is the request type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryResponse is the response type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionRequest is the request type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Code int32 `json:"code"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionResponse is the response type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// WebSocketConnect calls the websocket_connect host function.
|
// WebSocketConnect calls the websocket_connect host function.
|
||||||
// Connect establishes a WebSocket connection to the specified URL.
|
// Connect establishes a WebSocket connection to the specified URL.
|
||||||
//
|
//
|
||||||
@ -62,7 +94,7 @@ type WebSocketConnectResponse struct {
|
|||||||
// Returns the connection ID that can be used to send messages or close the connection,
|
// Returns the connection ID that can be used to send messages or close the connection,
|
||||||
// or an error if the connection fails.
|
// or an error if the connection fails.
|
||||||
func WebSocketConnect(url string, headers map[string]string, connectionID string) (*WebSocketConnectResponse, error) {
|
func WebSocketConnect(url string, headers map[string]string, connectionID string) (*WebSocketConnectResponse, error) {
|
||||||
// Create JSON request with all parameters
|
// Marshal request to JSON
|
||||||
req := WebSocketConnectRequest{
|
req := WebSocketConnectRequest{
|
||||||
Url: url,
|
Url: url,
|
||||||
Headers: headers,
|
Headers: headers,
|
||||||
@ -75,7 +107,7 @@ func WebSocketConnect(url string, headers map[string]string, connectionID string
|
|||||||
reqMem := pdk.AllocateBytes(reqBytes)
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
defer reqMem.Free()
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function with single JSON request
|
// Call the host function
|
||||||
responsePtr := websocket_connect(reqMem.Offset())
|
responsePtr := websocket_connect(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
@ -99,24 +131,33 @@ func WebSocketConnect(url string, headers map[string]string, connectionID string
|
|||||||
// - message: The text message to send
|
// - message: The text message to send
|
||||||
//
|
//
|
||||||
// Returns an error if the connection is not found or if sending fails.
|
// Returns an error if the connection is not found or if sending fails.
|
||||||
func WebSocketSendText(connectionID string, message string) error {
|
func WebSocketSendText(connectionID string, message string) (*WebSocketSendTextResponse, error) {
|
||||||
connectionIDMem := pdk.AllocateString(connectionID)
|
// Marshal request to JSON
|
||||||
defer connectionIDMem.Free()
|
req := WebSocketSendTextRequest{
|
||||||
messageMem := pdk.AllocateString(message)
|
ConnectionID: connectionID,
|
||||||
defer messageMem.Free()
|
Message: message,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := websocket_sendtext(connectionIDMem.Offset(), messageMem.Offset())
|
responsePtr := websocket_sendtext(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response WebSocketSendTextResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebSocketSendBinary calls the websocket_sendbinary host function.
|
// WebSocketSendBinary calls the websocket_sendbinary host function.
|
||||||
@ -127,24 +168,33 @@ func WebSocketSendText(connectionID string, message string) error {
|
|||||||
// - data: The binary data to send
|
// - data: The binary data to send
|
||||||
//
|
//
|
||||||
// Returns an error if the connection is not found or if sending fails.
|
// Returns an error if the connection is not found or if sending fails.
|
||||||
func WebSocketSendBinary(connectionID string, data []byte) error {
|
func WebSocketSendBinary(connectionID string, data []byte) (*WebSocketSendBinaryResponse, error) {
|
||||||
connectionIDMem := pdk.AllocateString(connectionID)
|
// Marshal request to JSON
|
||||||
defer connectionIDMem.Free()
|
req := WebSocketSendBinaryRequest{
|
||||||
dataMem := pdk.AllocateBytes(data)
|
ConnectionID: connectionID,
|
||||||
defer dataMem.Free()
|
Data: data,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := websocket_sendbinary(connectionIDMem.Offset(), dataMem.Offset())
|
responsePtr := websocket_sendbinary(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response WebSocketSendBinaryResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebSocketCloseConnection calls the websocket_closeconnection host function.
|
// WebSocketCloseConnection calls the websocket_closeconnection host function.
|
||||||
@ -156,22 +206,32 @@ func WebSocketSendBinary(connectionID string, data []byte) error {
|
|||||||
// - reason: Optional human-readable reason for closing
|
// - reason: Optional human-readable reason for closing
|
||||||
//
|
//
|
||||||
// Returns an error if the connection is not found or if closing fails.
|
// Returns an error if the connection is not found or if closing fails.
|
||||||
func WebSocketCloseConnection(connectionID string, code int32, reason string) error {
|
func WebSocketCloseConnection(connectionID string, code int32, reason string) (*WebSocketCloseConnectionResponse, error) {
|
||||||
connectionIDMem := pdk.AllocateString(connectionID)
|
// Marshal request to JSON
|
||||||
defer connectionIDMem.Free()
|
req := WebSocketCloseConnectionRequest{
|
||||||
reasonMem := pdk.AllocateString(reason)
|
ConnectionID: connectionID,
|
||||||
defer reasonMem.Free()
|
Code: code,
|
||||||
|
Reason: reason,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := websocket_closeconnection(connectionIDMem.Offset(), code, reasonMem.Offset())
|
responsePtr := websocket_closeconnection(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response WebSocketCloseConnectionResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,18 +9,42 @@ import (
|
|||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SchedulerScheduleOneTimeRequest is the request type for Scheduler.ScheduleOneTime.
|
||||||
|
type SchedulerScheduleOneTimeRequest struct {
|
||||||
|
DelaySeconds int32 `json:"delaySeconds"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
||||||
type SchedulerScheduleOneTimeResponse struct {
|
type SchedulerScheduleOneTimeResponse struct {
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulerScheduleRecurringRequest is the request type for Scheduler.ScheduleRecurring.
|
||||||
|
type SchedulerScheduleRecurringRequest struct {
|
||||||
|
CronExpression string `json:"cronExpression"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
||||||
type SchedulerScheduleRecurringResponse struct {
|
type SchedulerScheduleRecurringResponse struct {
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleRequest is the request type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleRequest struct {
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleResponse is the response type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterSchedulerHostFunctions registers Scheduler service host functions.
|
// RegisterSchedulerHostFunctions registers Scheduler service host functions.
|
||||||
// The returned host functions should be added to the plugin's configuration.
|
// The returned host functions should be added to the plugin's configuration.
|
||||||
func RegisterSchedulerHostFunctions(service SchedulerService) []extism.HostFunction {
|
func RegisterSchedulerHostFunctions(service SchedulerService) []extism.HostFunction {
|
||||||
@ -35,30 +59,32 @@ func newSchedulerScheduleOneTimeHostFunction(service SchedulerService) extism.Ho
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"scheduler_scheduleonetime",
|
"scheduler_scheduleonetime",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
delaySeconds := extism.DecodeI32(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
payload, err := p.ReadString(stack[1])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
scheduleID, err := p.ReadString(stack[2])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
newscheduleid, err := service.ScheduleOneTime(ctx, delaySeconds, payload, scheduleID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
schedulerWriteError(p, stack, err)
|
schedulerWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req SchedulerScheduleOneTimeRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
schedulerWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
newscheduleid, svcErr := service.ScheduleOneTime(ctx, req.DelaySeconds, req.Payload, req.ScheduleID)
|
||||||
|
if svcErr != nil {
|
||||||
|
schedulerWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := SchedulerScheduleOneTimeResponse{
|
resp := SchedulerScheduleOneTimeResponse{
|
||||||
NewScheduleID: newscheduleid,
|
NewScheduleID: newscheduleid,
|
||||||
}
|
}
|
||||||
schedulerWriteResponse(p, stack, resp)
|
schedulerWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypeI32, extism.ValueTypePTR, extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -67,33 +93,32 @@ func newSchedulerScheduleRecurringHostFunction(service SchedulerService) extism.
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"scheduler_schedulerecurring",
|
"scheduler_schedulerecurring",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
cronExpression, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
payload, err := p.ReadString(stack[1])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
scheduleID, err := p.ReadString(stack[2])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
newscheduleid, err := service.ScheduleRecurring(ctx, cronExpression, payload, scheduleID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
schedulerWriteError(p, stack, err)
|
schedulerWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req SchedulerScheduleRecurringRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
schedulerWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
newscheduleid, svcErr := service.ScheduleRecurring(ctx, req.CronExpression, req.Payload, req.ScheduleID)
|
||||||
|
if svcErr != nil {
|
||||||
|
schedulerWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := SchedulerScheduleRecurringResponse{
|
resp := SchedulerScheduleRecurringResponse{
|
||||||
NewScheduleID: newscheduleid,
|
NewScheduleID: newscheduleid,
|
||||||
}
|
}
|
||||||
schedulerWriteResponse(p, stack, resp)
|
schedulerWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypePTR, extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -102,25 +127,27 @@ func newSchedulerCancelScheduleHostFunction(service SchedulerService) extism.Hos
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"scheduler_cancelschedule",
|
"scheduler_cancelschedule",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
scheduleID, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
schedulerWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req SchedulerCancelScheduleRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
schedulerWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.CancelSchedule(ctx, scheduleID)
|
if svcErr := service.CancelSchedule(ctx, req.ScheduleID); svcErr != nil {
|
||||||
if err != nil {
|
schedulerWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := SchedulerCancelScheduleResponse{}
|
||||||
}
|
schedulerWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
|
|||||||
@ -9,6 +9,11 @@ import (
|
|||||||
extism "github.com/extism/go-sdk"
|
extism "github.com/extism/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SubsonicAPICallRequest is the request type for SubsonicAPI.Call.
|
||||||
|
type SubsonicAPICallRequest struct {
|
||||||
|
Uri string `json:"uri"`
|
||||||
|
}
|
||||||
|
|
||||||
// SubsonicAPICallResponse is the response type for SubsonicAPI.Call.
|
// SubsonicAPICallResponse is the response type for SubsonicAPI.Call.
|
||||||
type SubsonicAPICallResponse struct {
|
type SubsonicAPICallResponse struct {
|
||||||
ResponseJSON string `json:"responseJSON,omitempty"`
|
ResponseJSON string `json:"responseJSON,omitempty"`
|
||||||
@ -27,18 +32,25 @@ func newSubsonicAPICallHostFunction(service SubsonicAPIService) extism.HostFunct
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"subsonicapi_call",
|
"subsonicapi_call",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
uri, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the service method
|
|
||||||
responsejson, err := service.Call(ctx, uri)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
subsonicapiWriteError(p, stack, err)
|
subsonicapiWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var req SubsonicAPICallRequest
|
||||||
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
subsonicapiWriteError(p, stack, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the service method
|
||||||
|
responsejson, svcErr := service.Call(ctx, req.Uri)
|
||||||
|
if svcErr != nil {
|
||||||
|
subsonicapiWriteError(p, stack, svcErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := SubsonicAPICallResponse{
|
resp := SubsonicAPICallResponse{
|
||||||
ResponseJSON: responsejson,
|
ResponseJSON: responsejson,
|
||||||
|
|||||||
@ -22,6 +22,40 @@ type WebSocketConnectResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextRequest is the request type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextResponse is the response type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryRequest is the request type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryResponse is the response type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionRequest is the request type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Code int32 `json:"code"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionResponse is the response type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterWebSocketHostFunctions registers WebSocket service host functions.
|
// RegisterWebSocketHostFunctions registers WebSocket service host functions.
|
||||||
// The returned host functions should be added to the plugin's configuration.
|
// The returned host functions should be added to the plugin's configuration.
|
||||||
func RegisterWebSocketHostFunctions(service WebSocketService) []extism.HostFunction {
|
func RegisterWebSocketHostFunctions(service WebSocketService) []extism.HostFunction {
|
||||||
@ -50,11 +84,12 @@ func newWebSocketConnectHostFunction(service WebSocketService) extism.HostFuncti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
newconnectionid, err := service.Connect(ctx, req.Url, req.Headers, req.ConnectionID)
|
newconnectionid, svcErr := service.Connect(ctx, req.Url, req.Headers, req.ConnectionID)
|
||||||
if err != nil {
|
if svcErr != nil {
|
||||||
websocketWriteError(p, stack, err)
|
websocketWriteError(p, stack, svcErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write JSON response to plugin memory
|
// Write JSON response to plugin memory
|
||||||
resp := WebSocketConnectResponse{
|
resp := WebSocketConnectResponse{
|
||||||
NewConnectionID: newconnectionid,
|
NewConnectionID: newconnectionid,
|
||||||
@ -70,31 +105,29 @@ func newWebSocketSendTextHostFunction(service WebSocketService) extism.HostFunct
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"websocket_sendtext",
|
"websocket_sendtext",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
connectionID, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
websocketWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
message, err := p.ReadString(stack[1])
|
var req WebSocketSendTextRequest
|
||||||
if err != nil {
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
websocketWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.SendText(ctx, connectionID, message)
|
if svcErr := service.SendText(ctx, req.ConnectionID, req.Message); svcErr != nil {
|
||||||
if err != nil {
|
websocketWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := WebSocketSendTextResponse{}
|
||||||
}
|
websocketWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -103,31 +136,29 @@ func newWebSocketSendBinaryHostFunction(service WebSocketService) extism.HostFun
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"websocket_sendbinary",
|
"websocket_sendbinary",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
connectionID, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
websocketWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, err := p.ReadBytes(stack[1])
|
var req WebSocketSendBinaryRequest
|
||||||
if err != nil {
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
|
websocketWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.SendBinary(ctx, connectionID, data)
|
if svcErr := service.SendBinary(ctx, req.ConnectionID, req.Data); svcErr != nil {
|
||||||
if err != nil {
|
websocketWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := WebSocketSendBinaryResponse{}
|
||||||
}
|
websocketWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -136,32 +167,29 @@ func newWebSocketCloseConnectionHostFunction(service WebSocketService) extism.Ho
|
|||||||
return extism.NewHostFunctionWithStack(
|
return extism.NewHostFunctionWithStack(
|
||||||
"websocket_closeconnection",
|
"websocket_closeconnection",
|
||||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||||
// Read parameters from stack
|
// Read JSON request from plugin memory
|
||||||
connectionID, err := p.ReadString(stack[0])
|
reqBytes, err := p.ReadBytes(stack[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
websocketWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
code := extism.DecodeI32(stack[1])
|
var req WebSocketCloseConnectionRequest
|
||||||
reason, err := p.ReadString(stack[2])
|
if err := json.Unmarshal(reqBytes, &req); err != nil {
|
||||||
if err != nil {
|
websocketWriteError(p, stack, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the service method
|
// Call the service method
|
||||||
err = service.CloseConnection(ctx, connectionID, code, reason)
|
if svcErr := service.CloseConnection(ctx, req.ConnectionID, req.Code, req.Reason); svcErr != nil {
|
||||||
if err != nil {
|
websocketWriteError(p, stack, svcErr)
|
||||||
// Write error string to plugin memory
|
|
||||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
|
||||||
stack[0] = ptr
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write empty string to indicate success
|
|
||||||
if ptr, err := p.WriteString(""); err == nil {
|
// Write JSON response to plugin memory
|
||||||
stack[0] = ptr
|
resp := WebSocketCloseConnectionResponse{}
|
||||||
}
|
websocketWriteResponse(p, stack, resp)
|
||||||
},
|
},
|
||||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypeI32, extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
[]extism.ValueType{extism.ValueTypePTR},
|
[]extism.ValueType{extism.ValueTypePTR},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
92
plugins/testdata/fake-artwork/nd_host_artwork.go
vendored
92
plugins/testdata/fake-artwork/nd_host_artwork.go
vendored
@ -16,22 +16,28 @@ import (
|
|||||||
// artwork_getartisturl is the host function provided by Navidrome.
|
// artwork_getartisturl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_getartisturl
|
//go:wasmimport extism:host/user artwork_getartisturl
|
||||||
func artwork_getartisturl(uint64, int32) uint64
|
func artwork_getartisturl(uint64) uint64
|
||||||
|
|
||||||
// artwork_getalbumurl is the host function provided by Navidrome.
|
// artwork_getalbumurl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_getalbumurl
|
//go:wasmimport extism:host/user artwork_getalbumurl
|
||||||
func artwork_getalbumurl(uint64, int32) uint64
|
func artwork_getalbumurl(uint64) uint64
|
||||||
|
|
||||||
// artwork_gettrackurl is the host function provided by Navidrome.
|
// artwork_gettrackurl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_gettrackurl
|
//go:wasmimport extism:host/user artwork_gettrackurl
|
||||||
func artwork_gettrackurl(uint64, int32) uint64
|
func artwork_gettrackurl(uint64) uint64
|
||||||
|
|
||||||
// artwork_getplaylisturl is the host function provided by Navidrome.
|
// artwork_getplaylisturl is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user artwork_getplaylisturl
|
//go:wasmimport extism:host/user artwork_getplaylisturl
|
||||||
func artwork_getplaylisturl(uint64, int32) uint64
|
func artwork_getplaylisturl(uint64) uint64
|
||||||
|
|
||||||
|
// ArtworkGetArtistUrlRequest is the request type for Artwork.GetArtistUrl.
|
||||||
|
type ArtworkGetArtistUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetArtistUrlResponse is the response type for Artwork.GetArtistUrl.
|
// ArtworkGetArtistUrlResponse is the response type for Artwork.GetArtistUrl.
|
||||||
type ArtworkGetArtistUrlResponse struct {
|
type ArtworkGetArtistUrlResponse struct {
|
||||||
@ -39,18 +45,36 @@ type ArtworkGetArtistUrlResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetAlbumUrlRequest is the request type for Artwork.GetAlbumUrl.
|
||||||
|
type ArtworkGetAlbumUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetAlbumUrlResponse is the response type for Artwork.GetAlbumUrl.
|
// ArtworkGetAlbumUrlResponse is the response type for Artwork.GetAlbumUrl.
|
||||||
type ArtworkGetAlbumUrlResponse struct {
|
type ArtworkGetAlbumUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetTrackUrlRequest is the request type for Artwork.GetTrackUrl.
|
||||||
|
type ArtworkGetTrackUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetTrackUrlResponse is the response type for Artwork.GetTrackUrl.
|
// ArtworkGetTrackUrlResponse is the response type for Artwork.GetTrackUrl.
|
||||||
type ArtworkGetTrackUrlResponse struct {
|
type ArtworkGetTrackUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArtworkGetPlaylistUrlRequest is the request type for Artwork.GetPlaylistUrl.
|
||||||
|
type ArtworkGetPlaylistUrlRequest struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// ArtworkGetPlaylistUrlResponse is the response type for Artwork.GetPlaylistUrl.
|
// ArtworkGetPlaylistUrlResponse is the response type for Artwork.GetPlaylistUrl.
|
||||||
type ArtworkGetPlaylistUrlResponse struct {
|
type ArtworkGetPlaylistUrlResponse struct {
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
@ -66,11 +90,20 @@ type ArtworkGetPlaylistUrlResponse struct {
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetArtistUrl(id string, size int32) (*ArtworkGetArtistUrlResponse, error) {
|
func ArtworkGetArtistUrl(id string, size int32) (*ArtworkGetArtistUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetArtistUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_getartisturl(idMem.Offset(), size)
|
responsePtr := artwork_getartisturl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -94,11 +127,20 @@ func ArtworkGetArtistUrl(id string, size int32) (*ArtworkGetArtistUrlResponse, e
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetAlbumUrl(id string, size int32) (*ArtworkGetAlbumUrlResponse, error) {
|
func ArtworkGetAlbumUrl(id string, size int32) (*ArtworkGetAlbumUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetAlbumUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_getalbumurl(idMem.Offset(), size)
|
responsePtr := artwork_getalbumurl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -122,11 +164,20 @@ func ArtworkGetAlbumUrl(id string, size int32) (*ArtworkGetAlbumUrlResponse, err
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetTrackUrl(id string, size int32) (*ArtworkGetTrackUrlResponse, error) {
|
func ArtworkGetTrackUrl(id string, size int32) (*ArtworkGetTrackUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetTrackUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_gettrackurl(idMem.Offset(), size)
|
responsePtr := artwork_gettrackurl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -150,11 +201,20 @@ func ArtworkGetTrackUrl(id string, size int32) (*ArtworkGetTrackUrlResponse, err
|
|||||||
//
|
//
|
||||||
// Returns the public URL for the artwork, or an error if generation fails.
|
// Returns the public URL for the artwork, or an error if generation fails.
|
||||||
func ArtworkGetPlaylistUrl(id string, size int32) (*ArtworkGetPlaylistUrlResponse, error) {
|
func ArtworkGetPlaylistUrl(id string, size int32) (*ArtworkGetPlaylistUrlResponse, error) {
|
||||||
idMem := pdk.AllocateString(id)
|
// Marshal request to JSON
|
||||||
defer idMem.Free()
|
req := ArtworkGetPlaylistUrlRequest{
|
||||||
|
Id: id,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := artwork_getplaylisturl(idMem.Offset(), size)
|
responsePtr := artwork_getplaylisturl(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
@ -9,7 +9,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -17,30 +16,54 @@ import (
|
|||||||
// scheduler_scheduleonetime is the host function provided by Navidrome.
|
// scheduler_scheduleonetime is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user scheduler_scheduleonetime
|
//go:wasmimport extism:host/user scheduler_scheduleonetime
|
||||||
func scheduler_scheduleonetime(int32, uint64, uint64) uint64
|
func scheduler_scheduleonetime(uint64) uint64
|
||||||
|
|
||||||
// scheduler_schedulerecurring is the host function provided by Navidrome.
|
// scheduler_schedulerecurring is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user scheduler_schedulerecurring
|
//go:wasmimport extism:host/user scheduler_schedulerecurring
|
||||||
func scheduler_schedulerecurring(uint64, uint64, uint64) uint64
|
func scheduler_schedulerecurring(uint64) uint64
|
||||||
|
|
||||||
// scheduler_cancelschedule is the host function provided by Navidrome.
|
// scheduler_cancelschedule is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user scheduler_cancelschedule
|
//go:wasmimport extism:host/user scheduler_cancelschedule
|
||||||
func scheduler_cancelschedule(uint64) uint64
|
func scheduler_cancelschedule(uint64) uint64
|
||||||
|
|
||||||
|
// SchedulerScheduleOneTimeRequest is the request type for Scheduler.ScheduleOneTime.
|
||||||
|
type SchedulerScheduleOneTimeRequest struct {
|
||||||
|
DelaySeconds int32 `json:"delaySeconds"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
||||||
type SchedulerScheduleOneTimeResponse struct {
|
type SchedulerScheduleOneTimeResponse struct {
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulerScheduleRecurringRequest is the request type for Scheduler.ScheduleRecurring.
|
||||||
|
type SchedulerScheduleRecurringRequest struct {
|
||||||
|
CronExpression string `json:"cronExpression"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
||||||
type SchedulerScheduleRecurringResponse struct {
|
type SchedulerScheduleRecurringResponse struct {
|
||||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleRequest is the request type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleRequest struct {
|
||||||
|
ScheduleID string `json:"scheduleID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedulerCancelScheduleResponse is the response type for Scheduler.CancelSchedule.
|
||||||
|
type SchedulerCancelScheduleResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// SchedulerScheduleOneTime calls the scheduler_scheduleonetime host function.
|
// SchedulerScheduleOneTime calls the scheduler_scheduleonetime host function.
|
||||||
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
|
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
|
||||||
// Plugins that use this function must also implement the SchedulerCallback capability
|
// Plugins that use this function must also implement the SchedulerCallback capability
|
||||||
@ -52,13 +75,21 @@ type SchedulerScheduleRecurringResponse struct {
|
|||||||
//
|
//
|
||||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||||
func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID string) (*SchedulerScheduleOneTimeResponse, error) {
|
func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID string) (*SchedulerScheduleOneTimeResponse, error) {
|
||||||
payloadMem := pdk.AllocateString(payload)
|
// Marshal request to JSON
|
||||||
defer payloadMem.Free()
|
req := SchedulerScheduleOneTimeRequest{
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
DelaySeconds: delaySeconds,
|
||||||
defer scheduleIDMem.Free()
|
Payload: payload,
|
||||||
|
ScheduleID: scheduleID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := scheduler_scheduleonetime(delaySeconds, payloadMem.Offset(), scheduleIDMem.Offset())
|
responsePtr := scheduler_scheduleonetime(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -84,15 +115,21 @@ func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID str
|
|||||||
//
|
//
|
||||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||||
func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleID string) (*SchedulerScheduleRecurringResponse, error) {
|
func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleID string) (*SchedulerScheduleRecurringResponse, error) {
|
||||||
cronExpressionMem := pdk.AllocateString(cronExpression)
|
// Marshal request to JSON
|
||||||
defer cronExpressionMem.Free()
|
req := SchedulerScheduleRecurringRequest{
|
||||||
payloadMem := pdk.AllocateString(payload)
|
CronExpression: cronExpression,
|
||||||
defer payloadMem.Free()
|
Payload: payload,
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
ScheduleID: scheduleID,
|
||||||
defer scheduleIDMem.Free()
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := scheduler_schedulerecurring(cronExpressionMem.Offset(), payloadMem.Offset(), scheduleIDMem.Offset())
|
responsePtr := scheduler_schedulerecurring(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -114,20 +151,30 @@ func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleI
|
|||||||
// any future events.
|
// any future events.
|
||||||
//
|
//
|
||||||
// Returns an error if the schedule ID is not found or if cancellation fails.
|
// Returns an error if the schedule ID is not found or if cancellation fails.
|
||||||
func SchedulerCancelSchedule(scheduleID string) error {
|
func SchedulerCancelSchedule(scheduleID string) (*SchedulerCancelScheduleResponse, error) {
|
||||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
// Marshal request to JSON
|
||||||
defer scheduleIDMem.Free()
|
req := SchedulerCancelScheduleRequest{
|
||||||
|
ScheduleID: scheduleID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := scheduler_cancelschedule(scheduleIDMem.Offset())
|
responsePtr := scheduler_cancelschedule(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response SchedulerCancelScheduleResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
//
|
//
|
||||||
// This file contains client wrappers for the SubsonicAPI host service.
|
// This file contains client wrappers for the SubsonicAPI host service.
|
||||||
// It is intended for use in Navidrome plugins built with TinyGo.
|
// It is intended for use in Navidrome plugins built with TinyGo.
|
||||||
|
//
|
||||||
|
//go:build wasip1
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@ -16,6 +18,11 @@ import (
|
|||||||
//go:wasmimport extism:host/user subsonicapi_call
|
//go:wasmimport extism:host/user subsonicapi_call
|
||||||
func subsonicapi_call(uint64) uint64
|
func subsonicapi_call(uint64) uint64
|
||||||
|
|
||||||
|
// SubsonicAPICallRequest is the request type for SubsonicAPI.Call.
|
||||||
|
type SubsonicAPICallRequest struct {
|
||||||
|
Uri string `json:"uri"`
|
||||||
|
}
|
||||||
|
|
||||||
// SubsonicAPICallResponse is the response type for SubsonicAPI.Call.
|
// SubsonicAPICallResponse is the response type for SubsonicAPI.Call.
|
||||||
type SubsonicAPICallResponse struct {
|
type SubsonicAPICallResponse struct {
|
||||||
ResponseJSON string `json:"responseJSON,omitempty"`
|
ResponseJSON string `json:"responseJSON,omitempty"`
|
||||||
@ -28,11 +35,19 @@ type SubsonicAPICallResponse struct {
|
|||||||
// The uri parameter should be the Subsonic API path without the server prefix,
|
// The uri parameter should be the Subsonic API path without the server prefix,
|
||||||
// e.g., "getAlbumList2?type=random&size=10". The response is returned as raw JSON.
|
// e.g., "getAlbumList2?type=random&size=10". The response is returned as raw JSON.
|
||||||
func SubsonicAPICall(uri string) (*SubsonicAPICallResponse, error) {
|
func SubsonicAPICall(uri string) (*SubsonicAPICallResponse, error) {
|
||||||
uriMem := pdk.AllocateString(uri)
|
// Marshal request to JSON
|
||||||
defer uriMem.Free()
|
req := SubsonicAPICallRequest{
|
||||||
|
Uri: uri,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := subsonicapi_call(uriMem.Offset())
|
responsePtr := subsonicapi_call(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
|||||||
57
plugins/testdata/fake-websocket/main.go
vendored
57
plugins/testdata/fake-websocket/main.go
vendored
@ -4,7 +4,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
pdk "github.com/extism/go-pdk"
|
pdk "github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -82,20 +81,28 @@ func ndWebSocketOnTextMessage() int32 {
|
|||||||
|
|
||||||
switch input.Message {
|
switch input.Message {
|
||||||
case "echo":
|
case "echo":
|
||||||
err := webSocketSendText(input.ConnectionID, "echo:"+input.Message)
|
resp, err := WebSocketSendText(input.ConnectionID, "echo:"+input.Message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
errStr := err.Error()
|
||||||
pdk.OutputJSON(OnTextMessageOutput{Error: &errStr})
|
pdk.OutputJSON(OnTextMessageOutput{Error: &errStr})
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
pdk.OutputJSON(OnTextMessageOutput{Error: &resp.Error})
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
case "close":
|
case "close":
|
||||||
err := webSocketCloseConnection(input.ConnectionID)
|
resp, err := WebSocketCloseConnection(input.ConnectionID, 1000, "closed by plugin")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
errStr := err.Error()
|
||||||
pdk.OutputJSON(OnTextMessageOutput{Error: &errStr})
|
pdk.OutputJSON(OnTextMessageOutput{Error: &errStr})
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
pdk.OutputJSON(OnTextMessageOutput{Error: &resp.Error})
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
case "fail":
|
case "fail":
|
||||||
errStr := "intentional test failure"
|
errStr := "intentional test failure"
|
||||||
@ -205,48 +212,4 @@ func storeReceivedMessage(msg string) {
|
|||||||
pdk.SetVar("_received_messages", []byte(msg))
|
pdk.SetVar("_received_messages", []byte(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host function declarations for WebSocket operations
|
|
||||||
//
|
|
||||||
//go:wasmimport extism:host/user websocket_sendtext
|
|
||||||
func websocket_sendtext(connectionID uint64, message uint64) uint64
|
|
||||||
|
|
||||||
//go:wasmimport extism:host/user websocket_closeconnection
|
|
||||||
func websocket_closeconnection(connectionID uint64, code int32, reason uint64) uint64
|
|
||||||
|
|
||||||
// webSocketSendText sends a text message to the specified connection.
|
|
||||||
func webSocketSendText(connectionID, message string) error {
|
|
||||||
connMem := pdk.AllocateString(connectionID)
|
|
||||||
defer connMem.Free()
|
|
||||||
msgMem := pdk.AllocateString(message)
|
|
||||||
defer msgMem.Free()
|
|
||||||
|
|
||||||
responsePtr := websocket_sendtext(connMem.Offset(), msgMem.Offset())
|
|
||||||
if responsePtr != 0 {
|
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
|
||||||
errStr := string(responseMem.ReadBytes())
|
|
||||||
if errStr != "" {
|
|
||||||
return errors.New(errStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// webSocketCloseConnection closes the specified WebSocket connection.
|
|
||||||
func webSocketCloseConnection(connectionID string) error {
|
|
||||||
connMem := pdk.AllocateString(connectionID)
|
|
||||||
defer connMem.Free()
|
|
||||||
reasonMem := pdk.AllocateString("closed by plugin")
|
|
||||||
defer reasonMem.Free()
|
|
||||||
|
|
||||||
responsePtr := websocket_closeconnection(connMem.Offset(), 1000, reasonMem.Offset())
|
|
||||||
if responsePtr != 0 {
|
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
|
||||||
errStr := string(responseMem.ReadBytes())
|
|
||||||
if errStr != "" {
|
|
||||||
return errors.New(errStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {}
|
func main() {}
|
||||||
|
|||||||
237
plugins/testdata/fake-websocket/nd_host_websocket.go
vendored
Normal file
237
plugins/testdata/fake-websocket/nd_host_websocket.go
vendored
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
// Code generated by hostgen. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// This file contains client wrappers for the WebSocket host service.
|
||||||
|
// It is intended for use in Navidrome plugins built with TinyGo.
|
||||||
|
//
|
||||||
|
//go:build wasip1
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/extism/go-pdk"
|
||||||
|
)
|
||||||
|
|
||||||
|
// websocket_connect is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user websocket_connect
|
||||||
|
func websocket_connect(uint64) uint64
|
||||||
|
|
||||||
|
// websocket_sendtext is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user websocket_sendtext
|
||||||
|
func websocket_sendtext(uint64) uint64
|
||||||
|
|
||||||
|
// websocket_sendbinary is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user websocket_sendbinary
|
||||||
|
func websocket_sendbinary(uint64) uint64
|
||||||
|
|
||||||
|
// websocket_closeconnection is the host function provided by Navidrome.
|
||||||
|
//
|
||||||
|
//go:wasmimport extism:host/user websocket_closeconnection
|
||||||
|
func websocket_closeconnection(uint64) uint64
|
||||||
|
|
||||||
|
// WebSocketConnectRequest is the request type for WebSocket.Connect.
|
||||||
|
type WebSocketConnectRequest struct {
|
||||||
|
Url string `json:"url"`
|
||||||
|
Headers map[string]string `json:"headers"`
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketConnectResponse is the response type for WebSocket.Connect.
|
||||||
|
type WebSocketConnectResponse struct {
|
||||||
|
NewConnectionID string `json:"newConnectionID,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextRequest is the request type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendTextResponse is the response type for WebSocket.SendText.
|
||||||
|
type WebSocketSendTextResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryRequest is the request type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinaryResponse is the response type for WebSocket.SendBinary.
|
||||||
|
type WebSocketSendBinaryResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionRequest is the request type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionRequest struct {
|
||||||
|
ConnectionID string `json:"connectionID"`
|
||||||
|
Code int32 `json:"code"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnectionResponse is the response type for WebSocket.CloseConnection.
|
||||||
|
type WebSocketCloseConnectionResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketConnect calls the websocket_connect host function.
|
||||||
|
// Connect establishes a WebSocket connection to the specified URL.
|
||||||
|
//
|
||||||
|
// Plugins that use this function must also implement the WebSocketCallback capability
|
||||||
|
// to receive incoming messages and connection events.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - url: The WebSocket URL to connect to (ws:// or wss://)
|
||||||
|
// - headers: Optional HTTP headers to include in the handshake request
|
||||||
|
// - connectionID: Optional unique identifier for the connection. If empty, one will be generated
|
||||||
|
//
|
||||||
|
// Returns the connection ID that can be used to send messages or close the connection,
|
||||||
|
// or an error if the connection fails.
|
||||||
|
func WebSocketConnect(url string, headers map[string]string, connectionID string) (*WebSocketConnectResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := WebSocketConnectRequest{
|
||||||
|
Url: url,
|
||||||
|
Headers: headers,
|
||||||
|
ConnectionID: connectionID,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := websocket_connect(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response WebSocketConnectResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendText calls the websocket_sendtext host function.
|
||||||
|
// SendText sends a text message over an established WebSocket connection.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - connectionID: The connection identifier returned by Connect
|
||||||
|
// - message: The text message to send
|
||||||
|
//
|
||||||
|
// Returns an error if the connection is not found or if sending fails.
|
||||||
|
func WebSocketSendText(connectionID string, message string) (*WebSocketSendTextResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := WebSocketSendTextRequest{
|
||||||
|
ConnectionID: connectionID,
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := websocket_sendtext(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response WebSocketSendTextResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketSendBinary calls the websocket_sendbinary host function.
|
||||||
|
// SendBinary sends binary data over an established WebSocket connection.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - connectionID: The connection identifier returned by Connect
|
||||||
|
// - data: The binary data to send
|
||||||
|
//
|
||||||
|
// Returns an error if the connection is not found or if sending fails.
|
||||||
|
func WebSocketSendBinary(connectionID string, data []byte) (*WebSocketSendBinaryResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := WebSocketSendBinaryRequest{
|
||||||
|
ConnectionID: connectionID,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := websocket_sendbinary(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response WebSocketSendBinaryResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocketCloseConnection calls the websocket_closeconnection host function.
|
||||||
|
// CloseConnection gracefully closes a WebSocket connection.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - connectionID: The connection identifier returned by Connect
|
||||||
|
// - code: WebSocket close status code (e.g., 1000 for normal closure)
|
||||||
|
// - reason: Optional human-readable reason for closing
|
||||||
|
//
|
||||||
|
// Returns an error if the connection is not found or if closing fails.
|
||||||
|
func WebSocketCloseConnection(connectionID string, code int32, reason string) (*WebSocketCloseConnectionResponse, error) {
|
||||||
|
// Marshal request to JSON
|
||||||
|
req := WebSocketCloseConnectionRequest{
|
||||||
|
ConnectionID: connectionID,
|
||||||
|
Code: code,
|
||||||
|
Reason: reason,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
|
// Call the host function
|
||||||
|
responsePtr := websocket_closeconnection(reqMem.Offset())
|
||||||
|
|
||||||
|
// Read the response from memory
|
||||||
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var response WebSocketCloseConnectionResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
30
plugins/testdata/fake_cache_plugin/main.go
vendored
30
plugins/testdata/fake_cache_plugin/main.go
vendored
@ -81,12 +81,16 @@ func ndTestCache() int32 {
|
|||||||
|
|
||||||
switch input.Operation {
|
switch input.Operation {
|
||||||
case "set_string":
|
case "set_string":
|
||||||
err := CacheSetString(input.Key, input.StringVal, input.TTLSeconds)
|
resp, err := CacheSetString(input.Key, input.StringVal, input.TTLSeconds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
errStr := err.Error()
|
||||||
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
pdk.OutputJSON(TestCacheOutput{Error: &resp.Error})
|
||||||
|
return 0
|
||||||
|
}
|
||||||
pdk.OutputJSON(TestCacheOutput{})
|
pdk.OutputJSON(TestCacheOutput{})
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -105,12 +109,16 @@ func ndTestCache() int32 {
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
case "set_int":
|
case "set_int":
|
||||||
err := CacheSetInt(input.Key, input.IntVal, input.TTLSeconds)
|
resp, err := CacheSetInt(input.Key, input.IntVal, input.TTLSeconds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
errStr := err.Error()
|
||||||
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
pdk.OutputJSON(TestCacheOutput{Error: &resp.Error})
|
||||||
|
return 0
|
||||||
|
}
|
||||||
pdk.OutputJSON(TestCacheOutput{})
|
pdk.OutputJSON(TestCacheOutput{})
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -129,12 +137,16 @@ func ndTestCache() int32 {
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
case "set_float":
|
case "set_float":
|
||||||
err := CacheSetFloat(input.Key, input.FloatVal, input.TTLSeconds)
|
resp, err := CacheSetFloat(input.Key, input.FloatVal, input.TTLSeconds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
errStr := err.Error()
|
||||||
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
pdk.OutputJSON(TestCacheOutput{Error: &resp.Error})
|
||||||
|
return 0
|
||||||
|
}
|
||||||
pdk.OutputJSON(TestCacheOutput{})
|
pdk.OutputJSON(TestCacheOutput{})
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -153,12 +165,16 @@ func ndTestCache() int32 {
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
case "set_bytes":
|
case "set_bytes":
|
||||||
err := CacheSetBytes(input.Key, input.BytesVal, input.TTLSeconds)
|
resp, err := CacheSetBytes(input.Key, input.BytesVal, input.TTLSeconds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
errStr := err.Error()
|
||||||
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
pdk.OutputJSON(TestCacheOutput{Error: &resp.Error})
|
||||||
|
return 0
|
||||||
|
}
|
||||||
pdk.OutputJSON(TestCacheOutput{})
|
pdk.OutputJSON(TestCacheOutput{})
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -191,12 +207,16 @@ func ndTestCache() int32 {
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
case "remove":
|
case "remove":
|
||||||
err := CacheRemove(input.Key)
|
resp, err := CacheRemove(input.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
errStr := err.Error()
|
||||||
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
pdk.OutputJSON(TestCacheOutput{Error: &errStr})
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
pdk.OutputJSON(TestCacheOutput{Error: &resp.Error})
|
||||||
|
return 0
|
||||||
|
}
|
||||||
pdk.OutputJSON(TestCacheOutput{})
|
pdk.OutputJSON(TestCacheOutput{})
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
304
plugins/testdata/fake_cache_plugin/nd_host_cache.go
vendored
304
plugins/testdata/fake_cache_plugin/nd_host_cache.go
vendored
@ -9,7 +9,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/extism/go-pdk"
|
"github.com/extism/go-pdk"
|
||||||
)
|
)
|
||||||
@ -17,7 +16,7 @@ import (
|
|||||||
// cache_setstring is the host function provided by Navidrome.
|
// cache_setstring is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setstring
|
//go:wasmimport extism:host/user cache_setstring
|
||||||
func cache_setstring(uint64, uint64, int64) uint64
|
func cache_setstring(uint64) uint64
|
||||||
|
|
||||||
// cache_getstring is the host function provided by Navidrome.
|
// cache_getstring is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -27,7 +26,7 @@ func cache_getstring(uint64) uint64
|
|||||||
// cache_setint is the host function provided by Navidrome.
|
// cache_setint is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setint
|
//go:wasmimport extism:host/user cache_setint
|
||||||
func cache_setint(uint64, int64, int64) uint64
|
func cache_setint(uint64) uint64
|
||||||
|
|
||||||
// cache_getint is the host function provided by Navidrome.
|
// cache_getint is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -37,7 +36,7 @@ func cache_getint(uint64) uint64
|
|||||||
// cache_setfloat is the host function provided by Navidrome.
|
// cache_setfloat is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setfloat
|
//go:wasmimport extism:host/user cache_setfloat
|
||||||
func cache_setfloat(uint64, float64, int64) uint64
|
func cache_setfloat(uint64) uint64
|
||||||
|
|
||||||
// cache_getfloat is the host function provided by Navidrome.
|
// cache_getfloat is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -47,7 +46,7 @@ func cache_getfloat(uint64) uint64
|
|||||||
// cache_setbytes is the host function provided by Navidrome.
|
// cache_setbytes is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
//go:wasmimport extism:host/user cache_setbytes
|
//go:wasmimport extism:host/user cache_setbytes
|
||||||
func cache_setbytes(uint64, uint64, int64) uint64
|
func cache_setbytes(uint64) uint64
|
||||||
|
|
||||||
// cache_getbytes is the host function provided by Navidrome.
|
// cache_getbytes is the host function provided by Navidrome.
|
||||||
//
|
//
|
||||||
@ -64,6 +63,23 @@ func cache_has(uint64) uint64
|
|||||||
//go:wasmimport extism:host/user cache_remove
|
//go:wasmimport extism:host/user cache_remove
|
||||||
func cache_remove(uint64) uint64
|
func cache_remove(uint64) uint64
|
||||||
|
|
||||||
|
// CacheSetStringRequest is the request type for Cache.SetString.
|
||||||
|
type CacheSetStringRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetStringResponse is the response type for Cache.SetString.
|
||||||
|
type CacheSetStringResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetStringRequest is the request type for Cache.GetString.
|
||||||
|
type CacheGetStringRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetStringResponse is the response type for Cache.GetString.
|
// CacheGetStringResponse is the response type for Cache.GetString.
|
||||||
type CacheGetStringResponse struct {
|
type CacheGetStringResponse struct {
|
||||||
Value string `json:"value,omitempty"`
|
Value string `json:"value,omitempty"`
|
||||||
@ -71,6 +87,23 @@ type CacheGetStringResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetIntRequest is the request type for Cache.SetInt.
|
||||||
|
type CacheSetIntRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value int64 `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetIntResponse is the response type for Cache.SetInt.
|
||||||
|
type CacheSetIntResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetIntRequest is the request type for Cache.GetInt.
|
||||||
|
type CacheGetIntRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetIntResponse is the response type for Cache.GetInt.
|
// CacheGetIntResponse is the response type for Cache.GetInt.
|
||||||
type CacheGetIntResponse struct {
|
type CacheGetIntResponse struct {
|
||||||
Value int64 `json:"value,omitempty"`
|
Value int64 `json:"value,omitempty"`
|
||||||
@ -78,6 +111,23 @@ type CacheGetIntResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetFloatRequest is the request type for Cache.SetFloat.
|
||||||
|
type CacheSetFloatRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetFloatResponse is the response type for Cache.SetFloat.
|
||||||
|
type CacheSetFloatResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetFloatRequest is the request type for Cache.GetFloat.
|
||||||
|
type CacheGetFloatRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetFloatResponse is the response type for Cache.GetFloat.
|
// CacheGetFloatResponse is the response type for Cache.GetFloat.
|
||||||
type CacheGetFloatResponse struct {
|
type CacheGetFloatResponse struct {
|
||||||
Value float64 `json:"value,omitempty"`
|
Value float64 `json:"value,omitempty"`
|
||||||
@ -85,6 +135,23 @@ type CacheGetFloatResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheSetBytesRequest is the request type for Cache.SetBytes.
|
||||||
|
type CacheSetBytesRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value []byte `json:"value"`
|
||||||
|
TtlSeconds int64 `json:"ttlSeconds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheSetBytesResponse is the response type for Cache.SetBytes.
|
||||||
|
type CacheSetBytesResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheGetBytesRequest is the request type for Cache.GetBytes.
|
||||||
|
type CacheGetBytesRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheGetBytesResponse is the response type for Cache.GetBytes.
|
// CacheGetBytesResponse is the response type for Cache.GetBytes.
|
||||||
type CacheGetBytesResponse struct {
|
type CacheGetBytesResponse struct {
|
||||||
Value []byte `json:"value,omitempty"`
|
Value []byte `json:"value,omitempty"`
|
||||||
@ -92,12 +159,27 @@ type CacheGetBytesResponse struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheHasRequest is the request type for Cache.Has.
|
||||||
|
type CacheHasRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheHasResponse is the response type for Cache.Has.
|
// CacheHasResponse is the response type for Cache.Has.
|
||||||
type CacheHasResponse struct {
|
type CacheHasResponse struct {
|
||||||
Exists bool `json:"exists,omitempty"`
|
Exists bool `json:"exists,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheRemoveRequest is the request type for Cache.Remove.
|
||||||
|
type CacheRemoveRequest struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheRemoveResponse is the response type for Cache.Remove.
|
||||||
|
type CacheRemoveResponse struct {
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// CacheSetString calls the cache_setstring host function.
|
// CacheSetString calls the cache_setstring host function.
|
||||||
// SetString stores a string value in the cache.
|
// SetString stores a string value in the cache.
|
||||||
//
|
//
|
||||||
@ -107,24 +189,34 @@ type CacheHasResponse struct {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetString(key string, value string, ttlSeconds int64) error {
|
func CacheSetString(key string, value string, ttlSeconds int64) (*CacheSetStringResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetStringRequest{
|
||||||
valueMem := pdk.AllocateString(value)
|
Key: key,
|
||||||
defer valueMem.Free()
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setstring(keyMem.Offset(), valueMem.Offset(), ttlSeconds)
|
responsePtr := cache_setstring(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetStringResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetString calls the cache_getstring host function.
|
// CacheGetString calls the cache_getstring host function.
|
||||||
@ -136,11 +228,19 @@ func CacheSetString(key string, value string, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not a string, exists will be false.
|
// or the stored value is not a string, exists will be false.
|
||||||
func CacheGetString(key string) (*CacheGetStringResponse, error) {
|
func CacheGetString(key string) (*CacheGetStringResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetStringRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getstring(keyMem.Offset())
|
responsePtr := cache_getstring(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -164,22 +264,34 @@ func CacheGetString(key string) (*CacheGetStringResponse, error) {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetInt(key string, value int64, ttlSeconds int64) error {
|
func CacheSetInt(key string, value int64, ttlSeconds int64) (*CacheSetIntResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetIntRequest{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setint(keyMem.Offset(), value, ttlSeconds)
|
responsePtr := cache_setint(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetIntResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetInt calls the cache_getint host function.
|
// CacheGetInt calls the cache_getint host function.
|
||||||
@ -191,11 +303,19 @@ func CacheSetInt(key string, value int64, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not an integer, exists will be false.
|
// or the stored value is not an integer, exists will be false.
|
||||||
func CacheGetInt(key string) (*CacheGetIntResponse, error) {
|
func CacheGetInt(key string) (*CacheGetIntResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetIntRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getint(keyMem.Offset())
|
responsePtr := cache_getint(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -219,22 +339,34 @@ func CacheGetInt(key string) (*CacheGetIntResponse, error) {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetFloat(key string, value float64, ttlSeconds int64) error {
|
func CacheSetFloat(key string, value float64, ttlSeconds int64) (*CacheSetFloatResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetFloatRequest{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setfloat(keyMem.Offset(), value, ttlSeconds)
|
responsePtr := cache_setfloat(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetFloatResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetFloat calls the cache_getfloat host function.
|
// CacheGetFloat calls the cache_getfloat host function.
|
||||||
@ -246,11 +378,19 @@ func CacheSetFloat(key string, value float64, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not a float, exists will be false.
|
// or the stored value is not a float, exists will be false.
|
||||||
func CacheGetFloat(key string) (*CacheGetFloatResponse, error) {
|
func CacheGetFloat(key string) (*CacheGetFloatResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetFloatRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getfloat(keyMem.Offset())
|
responsePtr := cache_getfloat(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -274,24 +414,34 @@ func CacheGetFloat(key string) (*CacheGetFloatResponse, error) {
|
|||||||
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
// - ttlSeconds: Time-to-live in seconds (0 uses default of 24 hours)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails.
|
// Returns an error if the operation fails.
|
||||||
func CacheSetBytes(key string, value []byte, ttlSeconds int64) error {
|
func CacheSetBytes(key string, value []byte, ttlSeconds int64) (*CacheSetBytesResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheSetBytesRequest{
|
||||||
valueMem := pdk.AllocateBytes(value)
|
Key: key,
|
||||||
defer valueMem.Free()
|
Value: value,
|
||||||
|
TtlSeconds: ttlSeconds,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_setbytes(keyMem.Offset(), valueMem.Offset(), ttlSeconds)
|
responsePtr := cache_setbytes(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheSetBytesResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheGetBytes calls the cache_getbytes host function.
|
// CacheGetBytes calls the cache_getbytes host function.
|
||||||
@ -303,11 +453,19 @@ func CacheSetBytes(key string, value []byte, ttlSeconds int64) error {
|
|||||||
// Returns the value and whether the key exists. If the key doesn't exist
|
// Returns the value and whether the key exists. If the key doesn't exist
|
||||||
// or the stored value is not a byte slice, exists will be false.
|
// or the stored value is not a byte slice, exists will be false.
|
||||||
func CacheGetBytes(key string) (*CacheGetBytesResponse, error) {
|
func CacheGetBytes(key string) (*CacheGetBytesResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheGetBytesRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_getbytes(keyMem.Offset())
|
responsePtr := cache_getbytes(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -330,11 +488,19 @@ func CacheGetBytes(key string) (*CacheGetBytesResponse, error) {
|
|||||||
//
|
//
|
||||||
// Returns true if the key exists and has not expired.
|
// Returns true if the key exists and has not expired.
|
||||||
func CacheHas(key string) (*CacheHasResponse, error) {
|
func CacheHas(key string) (*CacheHasResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheHasRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_has(keyMem.Offset())
|
responsePtr := cache_has(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
@ -356,20 +522,30 @@ func CacheHas(key string) (*CacheHasResponse, error) {
|
|||||||
// - key: The cache key (will be namespaced with plugin ID)
|
// - key: The cache key (will be namespaced with plugin ID)
|
||||||
//
|
//
|
||||||
// Returns an error if the operation fails. Does not return an error if the key doesn't exist.
|
// Returns an error if the operation fails. Does not return an error if the key doesn't exist.
|
||||||
func CacheRemove(key string) error {
|
func CacheRemove(key string) (*CacheRemoveResponse, error) {
|
||||||
keyMem := pdk.AllocateString(key)
|
// Marshal request to JSON
|
||||||
defer keyMem.Free()
|
req := CacheRemoveRequest{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reqMem := pdk.AllocateBytes(reqBytes)
|
||||||
|
defer reqMem.Free()
|
||||||
|
|
||||||
// Call the host function
|
// Call the host function
|
||||||
responsePtr := cache_remove(keyMem.Offset())
|
responsePtr := cache_remove(reqMem.Offset())
|
||||||
|
|
||||||
// Read the response from memory
|
// Read the response from memory
|
||||||
responseMem := pdk.FindMemory(responsePtr)
|
responseMem := pdk.FindMemory(responsePtr)
|
||||||
errStr := string(responseMem.ReadBytes())
|
responseBytes := responseMem.ReadBytes()
|
||||||
|
|
||||||
if errStr != "" {
|
// Parse the response
|
||||||
return errors.New(errStr)
|
var response CacheRemoveResponse
|
||||||
|
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user