mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-31 07:30:32 +00:00
feat: add PDK abstraction layer with mock support for non-WASM builds
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
b95d3d7831
commit
363177e1d4
1
plugins/cmd/ndpgen/.gitignore
vendored
Normal file
1
plugins/cmd/ndpgen/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
ndpgen
|
||||
@ -3,21 +3,26 @@ module github.com/navidrome/navidrome/plugins/cmd/ndpgen
|
||||
go 1.25
|
||||
|
||||
require (
|
||||
github.com/onsi/ginkgo/v2 v2.22.2
|
||||
github.com/onsi/gomega v1.36.2
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/onsi/ginkgo/v2 v2.27.3
|
||||
github.com/onsi/gomega v1.38.3
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
golang.org/x/tools v0.40.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/tools v0.28.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/mod v0.31.0 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
)
|
||||
|
||||
@ -1,42 +1,80 @@
|
||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs=
|
||||
github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
|
||||
github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M=
|
||||
github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk=
|
||||
github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE=
|
||||
github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
|
||||
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
|
||||
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
|
||||
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
|
||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE=
|
||||
github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=
|
||||
github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
|
||||
github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=
|
||||
github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=
|
||||
github.com/onsi/ginkgo/v2 v2.27.3 h1:ICsZJ8JoYafeXFFlFAG75a7CxMsJHwgKwtO+82SE9L8=
|
||||
github.com/onsi/ginkgo/v2 v2.27.3/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
|
||||
github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM=
|
||||
github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
|
||||
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
||||
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@ -640,3 +640,220 @@ func GenerateCapabilityRustLib(capabilities []Capability) ([]byte, error) {
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// pdkFuncMap returns the template functions for PDK code generation.
|
||||
func pdkFuncMap() template.FuncMap {
|
||||
return template.FuncMap{
|
||||
"firstSentence": firstSentence,
|
||||
"paramList": pdkParamList,
|
||||
"returnList": pdkReturnList,
|
||||
"argList": pdkArgList,
|
||||
"argListWithReceiver": pdkArgListWithReceiver,
|
||||
"mockReturns": pdkMockReturns,
|
||||
"constValue": pdkConstValue,
|
||||
"stubTypeUnderlying": stubTypeUnderlying,
|
||||
"methodReceiver": pdkMethodReceiver,
|
||||
}
|
||||
}
|
||||
|
||||
// stubTypeUnderlying returns the appropriate stub type for non-WASM builds.
|
||||
// For types that reference internal packages (like memory.Memory), returns "struct{}".
|
||||
func stubTypeUnderlying(t PDKType) string {
|
||||
underlying := t.Underlying
|
||||
// If the underlying type references a package (contains a dot), use a stub struct
|
||||
if strings.Contains(underlying, ".") {
|
||||
return "struct{}"
|
||||
}
|
||||
// For simple types like int, int32, return as-is
|
||||
return underlying
|
||||
}
|
||||
|
||||
// firstSentence returns the first sentence of a doc string, normalized to a single line.
|
||||
func firstSentence(doc string) string {
|
||||
if doc == "" {
|
||||
return ""
|
||||
}
|
||||
// Normalize whitespace (replace newlines with spaces, collapse multiple spaces)
|
||||
doc = strings.Join(strings.Fields(doc), " ")
|
||||
|
||||
// Find first period followed by space or end
|
||||
for i, r := range doc {
|
||||
if r == '.' && (i+1 >= len(doc) || doc[i+1] == ' ') {
|
||||
return doc[:i+1]
|
||||
}
|
||||
}
|
||||
return doc
|
||||
}
|
||||
|
||||
// pdkParamList generates a parameter list string for function signature.
|
||||
func pdkParamList(params []PDKParam) string {
|
||||
var parts []string
|
||||
for _, p := range params {
|
||||
if p.Name != "" {
|
||||
parts = append(parts, p.Name+" "+p.Type)
|
||||
} else {
|
||||
parts = append(parts, p.Type)
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// pdkReturnList generates a return list string for function signature.
|
||||
func pdkReturnList(returns []PDKReturn) string {
|
||||
if len(returns) == 0 {
|
||||
return ""
|
||||
}
|
||||
if len(returns) == 1 && returns[0].Name == "" {
|
||||
return " " + returns[0].Type
|
||||
}
|
||||
var parts []string
|
||||
for _, r := range returns {
|
||||
if r.Name != "" {
|
||||
parts = append(parts, r.Name+" "+r.Type)
|
||||
} else {
|
||||
parts = append(parts, r.Type)
|
||||
}
|
||||
}
|
||||
return " (" + strings.Join(parts, ", ") + ")"
|
||||
}
|
||||
|
||||
// pdkArgList generates an argument list string for function call.
|
||||
func pdkArgList(params []PDKParam) string {
|
||||
var parts []string
|
||||
for _, p := range params {
|
||||
if p.Name != "" {
|
||||
parts = append(parts, p.Name)
|
||||
} else {
|
||||
parts = append(parts, "_")
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// pdkArgListWithReceiver generates an argument list that includes the receiver variable
|
||||
// as the first argument to PDKMock.Called(). This allows tests to verify which instance
|
||||
// a method was called on.
|
||||
func pdkArgListWithReceiver(params []PDKParam, typeName string) string {
|
||||
// Use lowercase first letter of type name as receiver variable
|
||||
receiverVar := strings.ToLower(typeName[:1])
|
||||
parts := []string{receiverVar}
|
||||
for _, p := range params {
|
||||
if p.Name != "" {
|
||||
parts = append(parts, p.Name)
|
||||
} else {
|
||||
parts = append(parts, "_")
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// pdkMethodReceiver generates the receiver declaration for a method.
|
||||
// Example: "r *HTTPRequest" or "m Memory"
|
||||
func pdkMethodReceiver(receiver, typeName string) string {
|
||||
receiverVar := strings.ToLower(typeName[:1])
|
||||
if strings.HasPrefix(receiver, "*") {
|
||||
return receiverVar + " *" + typeName
|
||||
}
|
||||
return receiverVar + " " + typeName
|
||||
}
|
||||
|
||||
// pdkMockReturns generates the mock return accessors for a function.
|
||||
func pdkMockReturns(returns []PDKReturn) string {
|
||||
var parts []string
|
||||
for i, r := range returns {
|
||||
parts = append(parts, mockAccessorForType(r.Type, i))
|
||||
}
|
||||
return strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// mockAccessorForType returns the testify mock accessor for a type.
|
||||
func mockAccessorForType(typ string, idx int) string {
|
||||
switch typ {
|
||||
case "string":
|
||||
return fmt.Sprintf("args.String(%d)", idx)
|
||||
case "bool":
|
||||
return fmt.Sprintf("args.Bool(%d)", idx)
|
||||
case "int":
|
||||
return fmt.Sprintf("args.Int(%d)", idx)
|
||||
case "error":
|
||||
return fmt.Sprintf("args.Error(%d)", idx)
|
||||
case "[]byte":
|
||||
return fmt.Sprintf("args.Get(%d).([]byte)", idx)
|
||||
case "uint64":
|
||||
return fmt.Sprintf("args.Get(%d).(uint64)", idx)
|
||||
case "uint32":
|
||||
return fmt.Sprintf("args.Get(%d).(uint32)", idx)
|
||||
case "uint16":
|
||||
return fmt.Sprintf("args.Get(%d).(uint16)", idx)
|
||||
default:
|
||||
return fmt.Sprintf("args.Get(%d).(%s)", idx, typ)
|
||||
}
|
||||
}
|
||||
|
||||
// pdkConstValue returns the value expression for a constant.
|
||||
func pdkConstValue(c PDKConst) string {
|
||||
if c.Value == "" || c.Value == "iota" {
|
||||
return "iota"
|
||||
}
|
||||
return c.Value
|
||||
}
|
||||
|
||||
// GeneratePDKGo generates the WASM implementation of the PDK wrapper package.
|
||||
func GeneratePDKGo(symbols *PDKSymbols) ([]byte, error) {
|
||||
tmplContent, err := templatesFS.ReadFile("templates/pdk.go.tmpl")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading pdk template: %w", err)
|
||||
}
|
||||
|
||||
tmpl, err := template.New("pdk").Funcs(pdkFuncMap()).Parse(string(tmplContent))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing template: %w", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tmpl.Execute(&buf, symbols); err != nil {
|
||||
return nil, fmt.Errorf("executing template: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// GeneratePDKGoStub generates the native stub implementation of the PDK wrapper package.
|
||||
func GeneratePDKGoStub(symbols *PDKSymbols) ([]byte, error) {
|
||||
tmplContent, err := templatesFS.ReadFile("templates/pdk_stub.go.tmpl")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading pdk stub template: %w", err)
|
||||
}
|
||||
|
||||
tmpl, err := template.New("pdk_stub").Funcs(pdkFuncMap()).Parse(string(tmplContent))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing template: %w", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tmpl.Execute(&buf, symbols); err != nil {
|
||||
return nil, fmt.Errorf("executing template: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// GeneratePDKTypesStub generates the native type definitions for the PDK wrapper package.
|
||||
func GeneratePDKTypesStub(symbols *PDKSymbols) ([]byte, error) {
|
||||
tmplContent, err := templatesFS.ReadFile("templates/types_stub.go.tmpl")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading types stub template: %w", err)
|
||||
}
|
||||
|
||||
tmpl, err := template.New("types_stub").Funcs(pdkFuncMap()).Parse(string(tmplContent))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing template: %w", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tmpl.Execute(&buf, symbols); err != nil {
|
||||
return nil, fmt.Errorf("executing template: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
441
plugins/cmd/ndpgen/internal/pdk_parser.go
Normal file
441
plugins/cmd/ndpgen/internal/pdk_parser.go
Normal file
@ -0,0 +1,441 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
// PDKSymbols contains all exported symbols parsed from extism/go-pdk.
|
||||
type PDKSymbols struct {
|
||||
Types []PDKType
|
||||
Consts []PDKConst
|
||||
Functions []PDKFunc
|
||||
}
|
||||
|
||||
// PDKType represents an exported type from extism/go-pdk.
|
||||
type PDKType struct {
|
||||
Name string
|
||||
Underlying string // The underlying type (e.g., "int" for LogLevel)
|
||||
IsAlias bool // True if it's a type alias (type X = Y)
|
||||
Doc string // Documentation comment
|
||||
Methods []PDKFunc // Methods on this type
|
||||
Fields []PDKField // Struct fields (if it's a struct type)
|
||||
}
|
||||
|
||||
// PDKField represents a struct field.
|
||||
type PDKField struct {
|
||||
Name string
|
||||
Type string
|
||||
Tag string // Struct tag (e.g., `json:"name"`)
|
||||
}
|
||||
|
||||
// PDKConst represents an exported constant from extism/go-pdk.
|
||||
type PDKConst struct {
|
||||
Name string
|
||||
Type string // The type name (may be empty for untyped consts)
|
||||
Value string // The value expression
|
||||
Doc string
|
||||
}
|
||||
|
||||
// PDKFunc represents an exported function from extism/go-pdk.
|
||||
type PDKFunc struct {
|
||||
Name string
|
||||
Doc string
|
||||
Receiver string // Empty for package-level functions
|
||||
Params []PDKParam
|
||||
Returns []PDKReturn
|
||||
IsVariadic bool
|
||||
}
|
||||
|
||||
// PDKParam represents a function parameter.
|
||||
type PDKParam struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// PDKReturn represents a function return value.
|
||||
type PDKReturn struct {
|
||||
Name string // May be empty for unnamed returns
|
||||
Type string
|
||||
}
|
||||
|
||||
// ParseExtismPDK parses the extism/go-pdk package and extracts all exported symbols.
|
||||
func ParseExtismPDK() (*PDKSymbols, error) {
|
||||
// Load both packages with syntax trees in one call
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.NeedName | packages.NeedSyntax | packages.NeedFiles,
|
||||
}
|
||||
pkgs, err := packages.Load(cfg,
|
||||
"github.com/extism/go-pdk",
|
||||
"github.com/extism/go-pdk/internal/memory",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("loading extism/go-pdk: %w", err)
|
||||
}
|
||||
|
||||
// Find both packages
|
||||
var pdkPkg, memoryPkg *packages.Package
|
||||
for _, pkg := range pkgs {
|
||||
if len(pkg.Errors) > 0 {
|
||||
return nil, fmt.Errorf("loading %s: %v", pkg.PkgPath, pkg.Errors[0])
|
||||
}
|
||||
switch pkg.Name {
|
||||
case "pdk":
|
||||
pdkPkg = pkg
|
||||
case "memory":
|
||||
memoryPkg = pkg
|
||||
}
|
||||
}
|
||||
if pdkPkg == nil {
|
||||
return nil, fmt.Errorf("package github.com/extism/go-pdk not found")
|
||||
}
|
||||
if memoryPkg == nil {
|
||||
return nil, fmt.Errorf("package github.com/extism/go-pdk/internal/memory not found")
|
||||
}
|
||||
|
||||
symbols := &PDKSymbols{}
|
||||
seenTypes := make(map[string]bool)
|
||||
|
||||
// Extract Memory type from internal/memory package first
|
||||
extractMemorySymbols(memoryPkg.Syntax, symbols, seenTypes)
|
||||
|
||||
// First pass: collect types from pdk package (skip if already found in internal packages)
|
||||
for _, file := range pdkPkg.Syntax {
|
||||
for _, decl := range file.Decls {
|
||||
if genDecl, ok := decl.(*ast.GenDecl); ok {
|
||||
for _, spec := range genDecl.Specs {
|
||||
if typeSpec, ok := spec.(*ast.TypeSpec); ok {
|
||||
if !typeSpec.Name.IsExported() {
|
||||
continue
|
||||
}
|
||||
// Skip if we already have this type (from internal packages)
|
||||
if seenTypes[typeSpec.Name.Name] {
|
||||
continue
|
||||
}
|
||||
seenTypes[typeSpec.Name.Name] = true
|
||||
pdkType := extractType(typeSpec, genDecl.Doc)
|
||||
symbols.Types = append(symbols.Types, pdkType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build typeMap from the final slice (after all types are added)
|
||||
typeMap := make(map[string]*PDKType)
|
||||
for i := range symbols.Types {
|
||||
typeMap[symbols.Types[i].Name] = &symbols.Types[i]
|
||||
}
|
||||
|
||||
// Second pass: collect functions and methods from pdk package
|
||||
for _, file := range pdkPkg.Syntax {
|
||||
for _, decl := range file.Decls {
|
||||
switch d := decl.(type) {
|
||||
case *ast.GenDecl:
|
||||
if d.Tok == token.CONST {
|
||||
consts := extractConsts(d)
|
||||
symbols.Consts = append(symbols.Consts, consts...)
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
if !d.Name.IsExported() {
|
||||
continue
|
||||
}
|
||||
fn := extractFunc(d)
|
||||
if fn.Receiver != "" {
|
||||
// It's a method, associate with type
|
||||
typeName := fn.Receiver
|
||||
if strings.HasPrefix(typeName, "*") {
|
||||
typeName = typeName[1:]
|
||||
}
|
||||
if t, ok := typeMap[typeName]; ok {
|
||||
t.Methods = append(t.Methods, fn)
|
||||
}
|
||||
} else {
|
||||
symbols.Functions = append(symbols.Functions, fn)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort for consistent output
|
||||
sort.Slice(symbols.Types, func(i, j int) bool {
|
||||
return symbols.Types[i].Name < symbols.Types[j].Name
|
||||
})
|
||||
sort.Slice(symbols.Consts, func(i, j int) bool {
|
||||
return symbols.Consts[i].Name < symbols.Consts[j].Name
|
||||
})
|
||||
sort.Slice(symbols.Functions, func(i, j int) bool {
|
||||
return symbols.Functions[i].Name < symbols.Functions[j].Name
|
||||
})
|
||||
|
||||
return symbols, nil
|
||||
}
|
||||
|
||||
func extractType(spec *ast.TypeSpec, doc *ast.CommentGroup) PDKType {
|
||||
t := PDKType{
|
||||
Name: spec.Name.Name,
|
||||
Doc: extractDoc(doc),
|
||||
}
|
||||
|
||||
// Check if it's an alias (type X = Y)
|
||||
t.IsAlias = spec.Assign.IsValid()
|
||||
|
||||
// Extract underlying type
|
||||
t.Underlying = typeString(spec.Type)
|
||||
|
||||
// Extract struct fields if it's a struct type
|
||||
if structType, ok := spec.Type.(*ast.StructType); ok {
|
||||
t.Fields = extractStructFields(structType)
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func extractStructFields(st *ast.StructType) []PDKField {
|
||||
var fields []PDKField
|
||||
if st.Fields == nil {
|
||||
return fields
|
||||
}
|
||||
|
||||
for _, field := range st.Fields.List {
|
||||
fieldType := typeString(field.Type)
|
||||
tag := ""
|
||||
if field.Tag != nil {
|
||||
tag = field.Tag.Value
|
||||
}
|
||||
|
||||
if len(field.Names) == 0 {
|
||||
// Embedded field
|
||||
fields = append(fields, PDKField{
|
||||
Name: fieldType, // Use type name as field name for embedded
|
||||
Type: fieldType,
|
||||
Tag: tag,
|
||||
})
|
||||
} else {
|
||||
for _, name := range field.Names {
|
||||
// Skip unexported fields
|
||||
if !name.IsExported() {
|
||||
continue
|
||||
}
|
||||
fields = append(fields, PDKField{
|
||||
Name: name.Name,
|
||||
Type: fieldType,
|
||||
Tag: tag,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func extractConsts(decl *ast.GenDecl) []PDKConst {
|
||||
var consts []PDKConst
|
||||
var currentType string // For iota-style const blocks
|
||||
|
||||
for i, spec := range decl.Specs {
|
||||
valSpec, ok := spec.(*ast.ValueSpec)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Update type if specified
|
||||
if valSpec.Type != nil {
|
||||
currentType = typeString(valSpec.Type)
|
||||
}
|
||||
|
||||
for j, name := range valSpec.Names {
|
||||
if !name.IsExported() {
|
||||
continue
|
||||
}
|
||||
|
||||
c := PDKConst{
|
||||
Name: name.Name,
|
||||
Type: currentType,
|
||||
}
|
||||
|
||||
// Extract value
|
||||
if j < len(valSpec.Values) {
|
||||
c.Value = exprString(valSpec.Values[j])
|
||||
} else if i == 0 && j == 0 {
|
||||
// First const with no value - likely iota
|
||||
c.Value = "iota"
|
||||
}
|
||||
|
||||
// Extract doc
|
||||
if valSpec.Doc != nil {
|
||||
c.Doc = extractDoc(valSpec.Doc)
|
||||
} else if i == 0 && decl.Doc != nil {
|
||||
c.Doc = extractDoc(decl.Doc)
|
||||
}
|
||||
|
||||
consts = append(consts, c)
|
||||
}
|
||||
}
|
||||
|
||||
return consts
|
||||
}
|
||||
|
||||
func extractFunc(decl *ast.FuncDecl) PDKFunc {
|
||||
fn := PDKFunc{
|
||||
Name: decl.Name.Name,
|
||||
Doc: extractDoc(decl.Doc),
|
||||
}
|
||||
|
||||
// Extract receiver
|
||||
if decl.Recv != nil && len(decl.Recv.List) > 0 {
|
||||
fn.Receiver = typeString(decl.Recv.List[0].Type)
|
||||
}
|
||||
|
||||
// Extract parameters
|
||||
if decl.Type.Params != nil {
|
||||
for _, field := range decl.Type.Params.List {
|
||||
paramType := typeString(field.Type)
|
||||
|
||||
// Check for variadic
|
||||
if _, ok := field.Type.(*ast.Ellipsis); ok {
|
||||
fn.IsVariadic = true
|
||||
}
|
||||
|
||||
if len(field.Names) == 0 {
|
||||
// Unnamed parameter
|
||||
fn.Params = append(fn.Params, PDKParam{Type: paramType})
|
||||
} else {
|
||||
for _, name := range field.Names {
|
||||
fn.Params = append(fn.Params, PDKParam{
|
||||
Name: name.Name,
|
||||
Type: paramType,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract returns
|
||||
if decl.Type.Results != nil {
|
||||
for _, field := range decl.Type.Results.List {
|
||||
retType := typeString(field.Type)
|
||||
|
||||
if len(field.Names) == 0 {
|
||||
// Unnamed return
|
||||
fn.Returns = append(fn.Returns, PDKReturn{Type: retType})
|
||||
} else {
|
||||
for _, name := range field.Names {
|
||||
fn.Returns = append(fn.Returns, PDKReturn{
|
||||
Name: name.Name,
|
||||
Type: retType,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fn
|
||||
}
|
||||
|
||||
func extractDoc(doc *ast.CommentGroup) string {
|
||||
if doc == nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(doc.Text())
|
||||
}
|
||||
|
||||
func typeString(expr ast.Expr) string {
|
||||
switch t := expr.(type) {
|
||||
case *ast.Ident:
|
||||
return t.Name
|
||||
case *ast.StarExpr:
|
||||
return "*" + typeString(t.X)
|
||||
case *ast.SelectorExpr:
|
||||
return typeString(t.X) + "." + t.Sel.Name
|
||||
case *ast.ArrayType:
|
||||
if t.Len == nil {
|
||||
return "[]" + typeString(t.Elt)
|
||||
}
|
||||
return fmt.Sprintf("[%s]%s", exprString(t.Len), typeString(t.Elt))
|
||||
case *ast.MapType:
|
||||
return fmt.Sprintf("map[%s]%s", typeString(t.Key), typeString(t.Value))
|
||||
case *ast.InterfaceType:
|
||||
return "any" // Simplified
|
||||
case *ast.Ellipsis:
|
||||
return "..." + typeString(t.Elt)
|
||||
case *ast.StructType:
|
||||
return "struct{}" // Simplified for anonymous structs
|
||||
case *ast.FuncType:
|
||||
return "func()" // Simplified
|
||||
default:
|
||||
return fmt.Sprintf("%T", expr)
|
||||
}
|
||||
}
|
||||
|
||||
func exprString(expr ast.Expr) string {
|
||||
switch e := expr.(type) {
|
||||
case *ast.Ident:
|
||||
return e.Name
|
||||
case *ast.BasicLit:
|
||||
return e.Value
|
||||
case *ast.BinaryExpr:
|
||||
return exprString(e.X) + " " + e.Op.String() + " " + exprString(e.Y)
|
||||
case *ast.UnaryExpr:
|
||||
return e.Op.String() + exprString(e.X)
|
||||
case *ast.CallExpr:
|
||||
return typeString(e.Fun) + "(...)"
|
||||
default:
|
||||
return fmt.Sprintf("%T", expr)
|
||||
}
|
||||
}
|
||||
|
||||
// extractMemorySymbols extracts the Memory type and its methods from already-parsed syntax trees.
|
||||
// This is needed because Memory is defined in internal/memory but re-exported by the pdk package.
|
||||
func extractMemorySymbols(files []*ast.File, symbols *PDKSymbols, seenTypes map[string]bool) {
|
||||
// Collect the Memory type
|
||||
for _, file := range files {
|
||||
for _, decl := range file.Decls {
|
||||
if genDecl, ok := decl.(*ast.GenDecl); ok {
|
||||
for _, spec := range genDecl.Specs {
|
||||
if typeSpec, ok := spec.(*ast.TypeSpec); ok {
|
||||
// Only interested in Memory type
|
||||
if typeSpec.Name.Name == "Memory" {
|
||||
pdkType := extractType(typeSpec, genDecl.Doc)
|
||||
symbols.Types = append(symbols.Types, pdkType)
|
||||
seenTypes["Memory"] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build local type map for method association
|
||||
localTypeMap := make(map[string]*PDKType)
|
||||
for i := range symbols.Types {
|
||||
localTypeMap[symbols.Types[i].Name] = &symbols.Types[i]
|
||||
}
|
||||
|
||||
// Collect methods for Memory
|
||||
for _, file := range files {
|
||||
for _, decl := range file.Decls {
|
||||
if funcDecl, ok := decl.(*ast.FuncDecl); ok {
|
||||
if !funcDecl.Name.IsExported() {
|
||||
continue
|
||||
}
|
||||
fn := extractFunc(funcDecl)
|
||||
if fn.Receiver != "" {
|
||||
typeName := fn.Receiver
|
||||
if strings.HasPrefix(typeName, "*") {
|
||||
typeName = typeName[1:]
|
||||
}
|
||||
if typeName == "Memory" {
|
||||
if t, ok := localTypeMap["Memory"]; ok {
|
||||
t.Methods = append(t.Methods, fn)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
package {{.Package}}
|
||||
|
||||
import (
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
{{- /* Generate type alias definitions */ -}}
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
{{- /* Generate struct definitions */ -}}
|
||||
|
||||
@ -2,4 +2,7 @@ module github.com/navidrome/navidrome/plugins/pdk/go
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/extism/go-pdk v1.1.3
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/stretchr/testify v1.11.1
|
||||
)
|
||||
|
||||
50
plugins/cmd/ndpgen/internal/templates/pdk.go.tmpl
Normal file
50
plugins/cmd/ndpgen/internal/templates/pdk.go.tmpl
Normal file
@ -0,0 +1,50 @@
|
||||
// Code generated by ndpgen. DO NOT EDIT.
|
||||
//
|
||||
// This file contains wrapper functions for the extism/go-pdk package.
|
||||
// For WASM builds, it provides type aliases and function wrappers that delegate
|
||||
// to the real extism/go-pdk package with zero overhead.
|
||||
//
|
||||
//go:build wasip1
|
||||
|
||||
package pdk
|
||||
|
||||
import (
|
||||
extism "github.com/extism/go-pdk"
|
||||
)
|
||||
|
||||
// Type aliases - zero overhead, full compatibility
|
||||
{{- range .Types}}
|
||||
type {{.Name}} = extism.{{.Name}}
|
||||
{{- end}}
|
||||
|
||||
// Constants
|
||||
{{- $prevType := ""}}
|
||||
{{- range .Consts}}
|
||||
{{- if ne .Type $prevType}}
|
||||
{{- if ne $prevType ""}}
|
||||
)
|
||||
{{- end}}
|
||||
|
||||
const (
|
||||
{{- end}}
|
||||
{{.Name}} = extism.{{.Name}}
|
||||
{{- $prevType = .Type}}
|
||||
{{- end}}
|
||||
{{- if ne $prevType ""}}
|
||||
)
|
||||
{{- end}}
|
||||
|
||||
// Functions
|
||||
{{- range .Functions}}
|
||||
|
||||
{{- if .Doc}}
|
||||
// {{.Name}} {{firstSentence .Doc}}
|
||||
{{- end}}
|
||||
func {{.Name}}({{paramList .Params}}){{returnList .Returns}} {
|
||||
{{- if .Returns}}
|
||||
return extism.{{.Name}}({{argList .Params}})
|
||||
{{- else}}
|
||||
extism.{{.Name}}({{argList .Params}})
|
||||
{{- end}}
|
||||
}
|
||||
{{- end}}
|
||||
42
plugins/cmd/ndpgen/internal/templates/pdk_stub.go.tmpl
Normal file
42
plugins/cmd/ndpgen/internal/templates/pdk_stub.go.tmpl
Normal file
@ -0,0 +1,42 @@
|
||||
// Code generated by ndpgen. DO NOT EDIT.
|
||||
//
|
||||
// This file contains mock implementations for non-WASM builds.
|
||||
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
|
||||
// Plugin authors can use the exported PDKMock instance to set expectations in tests.
|
||||
//
|
||||
//go:build !wasip1
|
||||
|
||||
package pdk
|
||||
|
||||
import "github.com/stretchr/testify/mock"
|
||||
|
||||
// MockPDK is the mock implementation for testing PDK functions.
|
||||
type MockPDK struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// PDKMock is the auto-instantiated mock instance for testing.
|
||||
// Use this to set expectations: pdk.PDKMock.On("GetConfig", "key").Return("value", true)
|
||||
var PDKMock = &MockPDK{}
|
||||
|
||||
// ResetMock resets the mock to its initial state.
|
||||
// Call this in test setup/teardown to ensure clean state between tests.
|
||||
func ResetMock() {
|
||||
PDKMock = &MockPDK{}
|
||||
}
|
||||
|
||||
// Functions
|
||||
{{- range .Functions}}
|
||||
|
||||
{{- if .Doc}}
|
||||
// {{.Name}} {{firstSentence .Doc}}
|
||||
{{- end}}
|
||||
func {{.Name}}({{paramList .Params}}){{returnList .Returns}} {
|
||||
{{- if .Returns}}
|
||||
args := PDKMock.Called({{argList .Params}})
|
||||
return {{mockReturns .Returns}}
|
||||
{{- else}}
|
||||
PDKMock.Called({{argList .Params}})
|
||||
{{- end}}
|
||||
}
|
||||
{{- end}}
|
||||
192
plugins/cmd/ndpgen/internal/templates/types_stub.go.tmpl
Normal file
192
plugins/cmd/ndpgen/internal/templates/types_stub.go.tmpl
Normal file
@ -0,0 +1,192 @@
|
||||
// Code generated by ndpgen. DO NOT EDIT.
|
||||
//
|
||||
// This file contains type definitions for non-WASM builds.
|
||||
// These types match the extism/go-pdk signatures to allow compilation and testing
|
||||
// on native platforms without importing the WASM-only extism package.
|
||||
//
|
||||
//go:build !wasip1
|
||||
|
||||
package pdk
|
||||
|
||||
// LogLevel represents a logging level.
|
||||
type LogLevel int
|
||||
|
||||
// Log level constants
|
||||
const (
|
||||
LogTrace LogLevel = iota
|
||||
LogDebug
|
||||
LogInfo
|
||||
LogWarn
|
||||
LogError
|
||||
)
|
||||
|
||||
// HTTPMethod represents an HTTP method.
|
||||
type HTTPMethod int32
|
||||
|
||||
// HTTP method constants
|
||||
const (
|
||||
MethodGet HTTPMethod = iota
|
||||
MethodHead
|
||||
MethodPost
|
||||
MethodPut
|
||||
MethodPatch
|
||||
MethodDelete
|
||||
MethodConnect
|
||||
MethodOptions
|
||||
MethodTrace
|
||||
)
|
||||
|
||||
// String returns the string representation of the HTTP method.
|
||||
func (m HTTPMethod) String() string {
|
||||
switch m {
|
||||
case MethodGet:
|
||||
return "GET"
|
||||
case MethodHead:
|
||||
return "HEAD"
|
||||
case MethodPost:
|
||||
return "POST"
|
||||
case MethodPut:
|
||||
return "PUT"
|
||||
case MethodPatch:
|
||||
return "PATCH"
|
||||
case MethodDelete:
|
||||
return "DELETE"
|
||||
case MethodConnect:
|
||||
return "CONNECT"
|
||||
case MethodOptions:
|
||||
return "OPTIONS"
|
||||
case MethodTrace:
|
||||
return "TRACE"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
// Memory represents memory allocated by (and shared with) the host.
|
||||
// This is a stub implementation for non-WASM platforms.
|
||||
type Memory struct {
|
||||
offset uint64
|
||||
length uint64
|
||||
data []byte
|
||||
}
|
||||
|
||||
// Offset returns the offset of the memory block.
|
||||
func (m Memory) Offset() uint64 {
|
||||
return m.offset
|
||||
}
|
||||
|
||||
// Length returns the length of the memory block.
|
||||
func (m Memory) Length() uint64 {
|
||||
return m.length
|
||||
}
|
||||
|
||||
// ReadBytes reads all bytes from the memory block.
|
||||
func (m Memory) ReadBytes() []byte {
|
||||
return m.data
|
||||
}
|
||||
|
||||
// Load reads the memory block into the provided buffer.
|
||||
func (m *Memory) Load(buffer []byte) {
|
||||
copy(buffer, m.data)
|
||||
}
|
||||
|
||||
// Store writes data to the memory block.
|
||||
func (m *Memory) Store(data []byte) {
|
||||
m.data = make([]byte, len(data))
|
||||
copy(m.data, data)
|
||||
m.length = uint64(len(data))
|
||||
}
|
||||
|
||||
// Free frees the memory block.
|
||||
func (m *Memory) Free() {
|
||||
m.data = nil
|
||||
m.length = 0
|
||||
}
|
||||
|
||||
// NewStubMemory creates a new stub Memory for testing.
|
||||
// This is a helper function not present in the real PDK.
|
||||
func NewStubMemory(offset, length uint64, data []byte) Memory {
|
||||
return Memory{
|
||||
offset: offset,
|
||||
length: length,
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPRequest represents an HTTP request sent by the host.
|
||||
// This is a stub implementation for non-WASM platforms.
|
||||
type HTTPRequest struct {
|
||||
method HTTPMethod
|
||||
url string
|
||||
headers map[string]string
|
||||
body []byte
|
||||
}
|
||||
|
||||
// SetHeader sets an HTTP header key to value.
|
||||
func (r *HTTPRequest) SetHeader(key string, value string) *HTTPRequest {
|
||||
if r.headers == nil {
|
||||
r.headers = make(map[string]string)
|
||||
}
|
||||
r.headers[key] = value
|
||||
return r
|
||||
}
|
||||
|
||||
// SetBody sets the HTTP request body.
|
||||
func (r *HTTPRequest) SetBody(body []byte) *HTTPRequest {
|
||||
r.body = body
|
||||
return r
|
||||
}
|
||||
|
||||
// Send sends the HTTP request and returns the response.
|
||||
// In the stub implementation, this delegates to the mock.
|
||||
func (r *HTTPRequest) Send() HTTPResponse {
|
||||
args := PDKMock.Called(r)
|
||||
return args.Get(0).(HTTPResponse)
|
||||
}
|
||||
|
||||
// HTTPRequestMeta represents the metadata associated with an HTTP request.
|
||||
type HTTPRequestMeta struct {
|
||||
URL string `json:"url"`
|
||||
Method string `json:"method"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
}
|
||||
|
||||
// HTTPResponse represents an HTTP response returned from the host.
|
||||
// This is a stub implementation for non-WASM platforms.
|
||||
type HTTPResponse struct {
|
||||
status uint16
|
||||
headers map[string]string
|
||||
body []byte
|
||||
memory Memory
|
||||
}
|
||||
|
||||
// Status returns the status code from the response.
|
||||
func (r HTTPResponse) Status() uint16 {
|
||||
return r.status
|
||||
}
|
||||
|
||||
// Headers returns the HTTP response headers.
|
||||
func (r *HTTPResponse) Headers() map[string]string {
|
||||
return r.headers
|
||||
}
|
||||
|
||||
// Body returns the body byte slice from the response.
|
||||
func (r HTTPResponse) Body() []byte {
|
||||
return r.body
|
||||
}
|
||||
|
||||
// Memory returns the memory associated with the response.
|
||||
func (r HTTPResponse) Memory() Memory {
|
||||
return r.memory
|
||||
}
|
||||
|
||||
// NewStubHTTPResponse creates a new stub HTTPResponse for testing.
|
||||
// This is a helper function not present in the real PDK.
|
||||
func NewStubHTTPResponse(status uint16, headers map[string]string, body []byte) HTTPResponse {
|
||||
return HTTPResponse{
|
||||
status: status,
|
||||
headers: headers,
|
||||
body: body,
|
||||
memory: NewStubMemory(0, uint64(len(body)), body),
|
||||
}
|
||||
}
|
||||
@ -62,6 +62,7 @@ type config struct {
|
||||
hostWrappers bool // Generate host wrappers (used by Navidrome server)
|
||||
capabilityOnly bool
|
||||
schemasOnly bool // Generate XTP schemas from capabilities (output goes to inputDir)
|
||||
pdkOnly bool // Generate PDK abstraction layer wrapper
|
||||
generateGoClient bool
|
||||
generatePyClient bool
|
||||
generateRsClient bool
|
||||
@ -84,6 +85,14 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.pdkOnly {
|
||||
if err := runPDKGeneration(cfg); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.capabilityOnly {
|
||||
if err := runCapabilityGeneration(cfg); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
@ -148,6 +157,128 @@ func runSchemaGeneration(cfg *config) error {
|
||||
return generateSchemas(cfg, capabilities)
|
||||
}
|
||||
|
||||
// runPDKGeneration handles PDK abstraction layer code generation.
|
||||
// This generates the pdk wrapper package that wraps extism/go-pdk
|
||||
// with mockable implementations for unit testing on native platforms.
|
||||
func runPDKGeneration(cfg *config) error {
|
||||
// Output directory is $output/go/pdk/
|
||||
outputDir := filepath.Join(cfg.outputDir, "go", "pdk")
|
||||
return generatePDKPackageWithParsing(outputDir, cfg.dryRun, cfg.verbose)
|
||||
}
|
||||
|
||||
// generatePDKPackageWithParsing generates the PDK abstraction layer using AST parsing.
|
||||
// It extracts all exported symbols from extism/go-pdk and generates wrappers for them.
|
||||
func generatePDKPackageWithParsing(outputDir string, dryRun, verbose bool) error {
|
||||
if verbose {
|
||||
fmt.Println("Parsing extism/go-pdk to extract exported symbols...")
|
||||
}
|
||||
|
||||
// Parse extism/go-pdk to get all exported symbols
|
||||
symbols, err := internal.ParseExtismPDK()
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing extism/go-pdk: %w", err)
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Printf("Found %d types, %d constants, %d functions\n",
|
||||
len(symbols.Types), len(symbols.Consts), len(symbols.Functions))
|
||||
for _, t := range symbols.Types {
|
||||
fmt.Printf(" Type %s: %d methods, %d fields\n", t.Name, len(t.Methods), len(t.Fields))
|
||||
for _, m := range t.Methods {
|
||||
fmt.Printf(" Method: %s (receiver: %s)\n", m.Name, m.Receiver)
|
||||
}
|
||||
}
|
||||
fmt.Printf("Generating PDK abstraction layer to: %s\n", outputDir)
|
||||
}
|
||||
|
||||
// Generate the WASM implementation (pdk.go)
|
||||
pdkCode, err := internal.GeneratePDKGo(symbols)
|
||||
if err != nil {
|
||||
return fmt.Errorf("generating pdk.go: %w", err)
|
||||
}
|
||||
|
||||
formatted, err := format.Source(pdkCode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("formatting pdk.go: %w\nRaw code:\n%s", err, pdkCode)
|
||||
}
|
||||
|
||||
pdkFile := filepath.Join(outputDir, "pdk.go")
|
||||
|
||||
if dryRun {
|
||||
fmt.Printf("=== %s ===\n%s\n", pdkFile, formatted)
|
||||
} else {
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
return fmt.Errorf("creating output directory: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(pdkFile, formatted, 0600); err != nil {
|
||||
return fmt.Errorf("writing pdk.go: %w", err)
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Printf("Generated: %s\n", pdkFile)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the types stub (types_stub.go)
|
||||
typesStubCode, err := internal.GeneratePDKTypesStub(symbols)
|
||||
if err != nil {
|
||||
return fmt.Errorf("generating types_stub.go: %w", err)
|
||||
}
|
||||
|
||||
formattedTypesStub, err := format.Source(typesStubCode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("formatting types_stub.go: %w\nRaw code:\n%s", err, typesStubCode)
|
||||
}
|
||||
|
||||
typesStubFile := filepath.Join(outputDir, "types_stub.go")
|
||||
|
||||
if dryRun {
|
||||
fmt.Printf("=== %s ===\n%s\n", typesStubFile, formattedTypesStub)
|
||||
} else {
|
||||
if err := os.WriteFile(typesStubFile, formattedTypesStub, 0600); err != nil {
|
||||
return fmt.Errorf("writing types_stub.go: %w", err)
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Printf("Generated: %s\n", typesStubFile)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the stub implementation (pdk_stub.go)
|
||||
stubCode, err := internal.GeneratePDKGoStub(symbols)
|
||||
if err != nil {
|
||||
return fmt.Errorf("generating pdk_stub.go: %w", err)
|
||||
}
|
||||
|
||||
formattedStub, err := format.Source(stubCode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("formatting pdk_stub.go: %w\nRaw code:\n%s", err, stubCode)
|
||||
}
|
||||
|
||||
stubFile := filepath.Join(outputDir, "pdk_stub.go")
|
||||
|
||||
if dryRun {
|
||||
fmt.Printf("=== %s ===\n%s\n", stubFile, formattedStub)
|
||||
} else {
|
||||
if err := os.WriteFile(stubFile, formattedStub, 0600); err != nil {
|
||||
return fmt.Errorf("writing pdk_stub.go: %w", err)
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Printf("Generated: %s\n", stubFile)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// generatePDKPackage generates the PDK abstraction layer to a specific directory.
|
||||
// This is called by generateAllCode to include the PDK package alongside host client code.
|
||||
func generatePDKPackage(outputDir string, dryRun, verbose bool) error {
|
||||
return generatePDKPackageWithParsing(outputDir, dryRun, verbose)
|
||||
}
|
||||
|
||||
// runHostWrapperGeneration handles host wrapper code generation.
|
||||
// This generates the *_gen.go files in the input directory that are used
|
||||
// by Navidrome server to expose host functions to plugins.
|
||||
@ -183,6 +314,7 @@ func parseConfig() (*config, error) {
|
||||
hostWrappers = flag.Bool("host-wrappers", false, "Generate host wrappers (used by Navidrome server, output to input directory)")
|
||||
capabilityOnly = flag.Bool("capability-only", false, "Generate only capability export wrappers")
|
||||
schemasOnly = flag.Bool("schemas", false, "Generate XTP YAML schemas from capabilities (output to input directory)")
|
||||
pdkOnly = flag.Bool("extism-pdk", false, "Generate PDK abstraction layer by parsing extism/go-pdk")
|
||||
goClient = flag.Bool("go", false, "Generate Go client wrappers")
|
||||
pyClient = flag.Bool("python", false, "Generate Python client wrappers")
|
||||
rsClient = flag.Bool("rust", false, "Generate Rust client wrappers")
|
||||
@ -205,6 +337,9 @@ func parseConfig() (*config, error) {
|
||||
if *schemasOnly {
|
||||
modeCount++
|
||||
}
|
||||
if *pdkOnly {
|
||||
modeCount++
|
||||
}
|
||||
|
||||
// Default to host-only if no mode is specified
|
||||
if modeCount == 0 {
|
||||
@ -213,7 +348,7 @@ func parseConfig() (*config, error) {
|
||||
|
||||
// Cannot specify multiple modes
|
||||
if modeCount > 1 {
|
||||
return nil, fmt.Errorf("cannot specify multiple modes (-host-only, -host-wrappers, -capability-only, -schemas)")
|
||||
return nil, fmt.Errorf("cannot specify multiple modes (-host-only, -host-wrappers, -capability-only, -schemas, -pdk)")
|
||||
}
|
||||
|
||||
if *outputDir == "" {
|
||||
@ -260,6 +395,7 @@ func parseConfig() (*config, error) {
|
||||
hostWrappers: *hostWrappers,
|
||||
capabilityOnly: *capabilityOnly,
|
||||
schemasOnly: *schemasOnly,
|
||||
pdkOnly: *pdkOnly,
|
||||
generateGoClient: *goClient || !anyLangFlag,
|
||||
generatePyClient: *pyClient,
|
||||
generateRsClient: *rsClient,
|
||||
@ -508,6 +644,11 @@ func generateAllCode(cfg *config, services []internal.Service) error {
|
||||
if err := generateGoModFile(cfg.goOutputDir, cfg.dryRun, cfg.verbose); err != nil {
|
||||
return fmt.Errorf("generating Go go.mod: %w", err)
|
||||
}
|
||||
// Generate PDK abstraction layer alongside host client code
|
||||
pdkDir := filepath.Join(filepath.Dir(cfg.goOutputDir), "pdk")
|
||||
if err := generatePDKPackage(pdkDir, cfg.dryRun, cfg.verbose); err != nil {
|
||||
return fmt.Errorf("generating PDK package: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// codec_encode is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// counter_count is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// echo_echo is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// Filter represents the Filter data structure.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// math_add is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// meta_get is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// ping_ping is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// Result represents the Result data structure.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// Item represents the Item data structure.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// User represents the User data structure.
|
||||
|
||||
8
plugins/cmd/ndpgen/tools.go
Normal file
8
plugins/cmd/ndpgen/tools.go
Normal file
@ -0,0 +1,8 @@
|
||||
//go:build tools
|
||||
|
||||
// This file ensures the extism/go-pdk dependency stays in go.mod.
|
||||
// The PDK parser loads this package at runtime using go/packages.
|
||||
// Without this import, `go mod tidy` would remove it since it's not directly imported elsewhere.
|
||||
package main
|
||||
|
||||
import _ "github.com/extism/go-pdk"
|
||||
@ -2,9 +2,15 @@ module crypto-ticker
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@ -9,9 +9,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/lifecycle"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/scheduler"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/websocket"
|
||||
)
|
||||
|
||||
@ -2,13 +2,11 @@ module discord-rich-presence
|
||||
|
||||
go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
|
||||
@ -15,8 +15,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/scheduler"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/scrobbler"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/websocket"
|
||||
|
||||
@ -10,8 +10,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
host "github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/websocket"
|
||||
)
|
||||
|
||||
|
||||
@ -4,6 +4,13 @@ go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require github.com/extism/go-pdk v1.1.3 // indirect
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@ -2,9 +2,15 @@ module wikimedia-plugin
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@ -14,8 +14,8 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/metadata"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// wikimediaPlugin implements the metadata provider interfaces for the methods we support.
|
||||
|
||||
@ -255,6 +255,66 @@ make plugin.wasm
|
||||
The PDK includes [testify/mock](https://github.com/stretchr/testify) implementations for all host services,
|
||||
allowing you to unit test your plugin code on non-WASM platforms (your development machine).
|
||||
|
||||
### PDK Abstraction Layer
|
||||
|
||||
The `pdk` subpackage provides a testable wrapper around the Extism PDK functions. Instead of importing
|
||||
`github.com/extism/go-pdk` directly, import the abstraction layer:
|
||||
|
||||
```go
|
||||
import "github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
|
||||
func myFunction() {
|
||||
// Use pdk functions - same API as extism/go-pdk
|
||||
config, ok := pdk.GetConfig("my_setting")
|
||||
if ok {
|
||||
pdk.Log(pdk.LogInfo, "Setting: " + config)
|
||||
}
|
||||
|
||||
var input MyInput
|
||||
if err := pdk.InputJSON(&input); err != nil {
|
||||
pdk.SetError(err)
|
||||
return
|
||||
}
|
||||
|
||||
output := processInput(input)
|
||||
pdk.OutputJSON(output)
|
||||
}
|
||||
```
|
||||
|
||||
For WASM builds, these functions delegate directly to `extism/go-pdk` with zero overhead.
|
||||
For native builds (tests), they use mocks that you can configure:
|
||||
|
||||
```go
|
||||
package myplugin
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
func TestMyFunction(t *testing.T) {
|
||||
// Reset mock state before each test
|
||||
pdk.ResetMock()
|
||||
|
||||
// Set up expectations
|
||||
pdk.PDKMock.On("GetConfig", "my_setting").Return("test_value", true)
|
||||
pdk.PDKMock.On("Log", pdk.LogInfo, "Setting: test_value").Return()
|
||||
pdk.PDKMock.On("InputJSON", mock.Anything).Return(nil).Run(func(args mock.Arguments) {
|
||||
// Populate the input struct
|
||||
input := args.Get(0).(*MyInput)
|
||||
input.Name = "test"
|
||||
})
|
||||
pdk.PDKMock.On("OutputJSON", mock.Anything).Return(nil)
|
||||
|
||||
// Call your function
|
||||
myFunction()
|
||||
|
||||
// Verify expectations
|
||||
pdk.PDKMock.AssertExpectations(t)
|
||||
}
|
||||
```
|
||||
|
||||
### Mock Instances
|
||||
|
||||
Each host service has an auto-instantiated mock instance:
|
||||
@ -312,3 +372,8 @@ go test ./...
|
||||
|
||||
The stub files with mocks are only compiled for non-WASM builds (`//go:build !wasip1`),
|
||||
so they won't affect your production WASM binary.
|
||||
|
||||
### Complete Examples
|
||||
|
||||
For more comprehensive examples including HTTP requests, Memory handling, and various testing patterns,
|
||||
see [pdk/example_test.go](pdk/example_test.go).
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// artwork_getartisturl is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// cache_setstring is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// kvstore_set is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// Library represents the Library data structure.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// scheduler_scheduleonetime is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// subsonicapi_call is the host function provided by Navidrome.
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// websocket_connect is the host function provided by Navidrome.
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
package lifecycle
|
||||
|
||||
import (
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// Lifecycle is the marker interface for lifecycle plugins.
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
package metadata
|
||||
|
||||
import (
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// AlbumImagesResponse is the response for GetAlbumImages.
|
||||
|
||||
324
plugins/pdk/go/pdk/example_test.go
Normal file
324
plugins/pdk/go/pdk/example_test.go
Normal file
@ -0,0 +1,324 @@
|
||||
// Example test demonstrating how to use the PDK mock for unit testing.
|
||||
// This file is only compiled for non-WASM builds.
|
||||
//
|
||||
//go:build !wasip1
|
||||
|
||||
package pdk_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// ExamplePlugin demonstrates a simple plugin that uses PDK functions.
|
||||
type ExamplePlugin struct{}
|
||||
|
||||
// ProcessMessage reads input, logs it, and outputs a response.
|
||||
func (p *ExamplePlugin) ProcessMessage() error {
|
||||
// Get configuration
|
||||
prefix, ok := pdk.GetConfig("message_prefix")
|
||||
if !ok {
|
||||
prefix = "Hello"
|
||||
}
|
||||
|
||||
// Read input
|
||||
message := pdk.InputString()
|
||||
|
||||
// Log the message
|
||||
pdk.Log(pdk.LogInfo, "Processing: "+message)
|
||||
|
||||
// Output the response
|
||||
pdk.OutputString(prefix + ", " + message + "!")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestExamplePlugin_ProcessMessage(t *testing.T) {
|
||||
// Reset mock state before the test
|
||||
pdk.ResetMock()
|
||||
|
||||
// Set up expectations
|
||||
pdk.PDKMock.On("GetConfig", "message_prefix").Return("Hi", true)
|
||||
pdk.PDKMock.On("InputString").Return("World")
|
||||
pdk.PDKMock.On("Log", pdk.LogInfo, "Processing: World").Return()
|
||||
pdk.PDKMock.On("OutputString", "Hi, World!").Return()
|
||||
|
||||
// Call the plugin function
|
||||
plugin := &ExamplePlugin{}
|
||||
err := plugin.ProcessMessage()
|
||||
|
||||
// Verify no error
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Verify all expected calls were made
|
||||
pdk.PDKMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestExamplePlugin_ProcessMessage_DefaultPrefix(t *testing.T) {
|
||||
// Reset mock state before the test
|
||||
pdk.ResetMock()
|
||||
|
||||
// Set up expectations - config key not found
|
||||
pdk.PDKMock.On("GetConfig", "message_prefix").Return("", false)
|
||||
pdk.PDKMock.On("InputString").Return("Test")
|
||||
pdk.PDKMock.On("Log", pdk.LogInfo, "Processing: Test").Return()
|
||||
pdk.PDKMock.On("OutputString", "Hello, Test!").Return()
|
||||
|
||||
// Call the plugin function
|
||||
plugin := &ExamplePlugin{}
|
||||
err := plugin.ProcessMessage()
|
||||
|
||||
// Verify no error
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Verify all expected calls were made
|
||||
pdk.PDKMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
// Example of testing JSON input/output
|
||||
type Request struct {
|
||||
Name string `json:"name"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Message string `json:"message"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
func ProcessJSONRequest() error {
|
||||
var req Request
|
||||
if err := pdk.InputJSON(&req); err != nil {
|
||||
pdk.SetError(err)
|
||||
return err
|
||||
}
|
||||
|
||||
resp := Response{
|
||||
Message: "Hello, " + req.Name,
|
||||
Total: req.Count * 2,
|
||||
}
|
||||
|
||||
return pdk.OutputJSON(resp)
|
||||
}
|
||||
|
||||
func TestProcessJSONRequest(t *testing.T) {
|
||||
pdk.ResetMock()
|
||||
|
||||
// Mock InputJSON to populate the request struct
|
||||
pdk.PDKMock.On("InputJSON", mock.AnythingOfType("*pdk_test.Request")).
|
||||
Return(nil).
|
||||
Run(func(args mock.Arguments) {
|
||||
req := args.Get(0).(*Request)
|
||||
req.Name = "Alice"
|
||||
req.Count = 5
|
||||
})
|
||||
|
||||
// Expect OutputJSON with the correct response
|
||||
pdk.PDKMock.On("OutputJSON", Response{
|
||||
Message: "Hello, Alice",
|
||||
Total: 10,
|
||||
}).Return(nil)
|
||||
|
||||
// Call the function
|
||||
err := ProcessJSONRequest()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
pdk.PDKMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Examples using stub types (Memory, HTTPRequest, HTTPResponse)
|
||||
// =============================================================================
|
||||
|
||||
// FetchData demonstrates a plugin function that makes an HTTP request.
|
||||
func FetchData(url string) ([]byte, error) {
|
||||
// Create and configure the HTTP request
|
||||
// Note: SetHeader and SetBody work directly on the stub - no mocking needed!
|
||||
req := pdk.NewHTTPRequest(pdk.MethodGet, url)
|
||||
req.SetHeader("Accept", "application/json")
|
||||
req.SetHeader("User-Agent", "MyPlugin/1.0")
|
||||
|
||||
// Send the request - this is mocked because it requires host interaction
|
||||
resp := req.Send()
|
||||
|
||||
// Check status - works directly on the stub
|
||||
if resp.Status() != 200 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Return body - works directly on the stub
|
||||
return resp.Body(), nil
|
||||
}
|
||||
|
||||
func TestFetchData(t *testing.T) {
|
||||
pdk.ResetMock()
|
||||
|
||||
// Create a stub response with test data
|
||||
expectedBody := []byte(`{"result": "success"}`)
|
||||
stubResponse := pdk.NewStubHTTPResponse(200, map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}, expectedBody)
|
||||
|
||||
// Mock NewHTTPRequest to return a real HTTPRequest struct
|
||||
// The struct methods (SetHeader, SetBody) work without mocking
|
||||
pdk.PDKMock.On("NewHTTPRequest", pdk.MethodGet, "https://api.example.com/data").
|
||||
Return(&pdk.HTTPRequest{})
|
||||
|
||||
// Mock Send to return our stub response
|
||||
pdk.PDKMock.On("Send", mock.AnythingOfType("*pdk.HTTPRequest")).
|
||||
Return(stubResponse)
|
||||
|
||||
// Call the function
|
||||
body, err := FetchData("https://api.example.com/data")
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if string(body) != string(expectedBody) {
|
||||
t.Errorf("expected body %q, got %q", expectedBody, body)
|
||||
}
|
||||
|
||||
pdk.PDKMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestFetchData_NonOKStatus(t *testing.T) {
|
||||
pdk.ResetMock()
|
||||
|
||||
// Create a stub response with 404 status
|
||||
stubResponse := pdk.NewStubHTTPResponse(404, nil, []byte("Not Found"))
|
||||
|
||||
pdk.PDKMock.On("NewHTTPRequest", pdk.MethodGet, "https://api.example.com/missing").
|
||||
Return(&pdk.HTTPRequest{})
|
||||
pdk.PDKMock.On("Send", mock.AnythingOfType("*pdk.HTTPRequest")).
|
||||
Return(stubResponse)
|
||||
|
||||
// Call the function
|
||||
body, err := FetchData("https://api.example.com/missing")
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Should return nil for non-200 status
|
||||
if body != nil {
|
||||
t.Errorf("expected nil body for 404, got %q", body)
|
||||
}
|
||||
|
||||
pdk.PDKMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
// ProcessMemoryData demonstrates working with Memory type.
|
||||
func ProcessMemoryData(mem pdk.Memory) string {
|
||||
// Memory methods work directly on the stub - no mocking needed!
|
||||
data := mem.ReadBytes()
|
||||
return "Processed " + string(data) + " (length: " + formatUint64(mem.Length()) + ")"
|
||||
}
|
||||
|
||||
func formatUint64(n uint64) string {
|
||||
return string(rune('0' + n%10)) // Simplified for demo
|
||||
}
|
||||
|
||||
func TestProcessMemoryData(t *testing.T) {
|
||||
// Create stub memory with test data - no mocking needed!
|
||||
mem := pdk.NewStubMemory(0, 5, []byte("hello"))
|
||||
|
||||
result := ProcessMemoryData(mem)
|
||||
|
||||
expected := "Processed hello (length: 5)"
|
||||
if result != expected {
|
||||
t.Errorf("expected %q, got %q", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
// StoreAndRetrieve demonstrates Memory Store/Load methods.
|
||||
func TestMemoryStoreAndLoad(t *testing.T) {
|
||||
// Create empty memory
|
||||
mem := pdk.NewStubMemory(100, 0, nil)
|
||||
|
||||
// Store data - works directly, no mock needed
|
||||
mem.Store([]byte("test data"))
|
||||
|
||||
// Verify the data was stored
|
||||
if mem.Length() != 9 {
|
||||
t.Errorf("expected length 9, got %d", mem.Length())
|
||||
}
|
||||
|
||||
// Load into buffer
|
||||
buffer := make([]byte, 9)
|
||||
mem.Load(buffer)
|
||||
|
||||
if string(buffer) != "test data" {
|
||||
t.Errorf("expected 'test data', got %q", buffer)
|
||||
}
|
||||
|
||||
// Free the memory
|
||||
mem.Free()
|
||||
|
||||
if mem.Length() != 0 {
|
||||
t.Errorf("expected length 0 after free, got %d", mem.Length())
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPMethodString demonstrates that HTTPMethod.String() works without mocking.
|
||||
func TestHTTPMethodString(t *testing.T) {
|
||||
// These work directly - no mocking needed!
|
||||
tests := []struct {
|
||||
method pdk.HTTPMethod
|
||||
expected string
|
||||
}{
|
||||
{pdk.MethodGet, "GET"},
|
||||
{pdk.MethodPost, "POST"},
|
||||
{pdk.MethodPut, "PUT"},
|
||||
{pdk.MethodDelete, "DELETE"},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
result := tc.method.String()
|
||||
if result != tc.expected {
|
||||
t.Errorf("expected %q for method %d, got %q", tc.expected, tc.method, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PostJSON demonstrates a more complex HTTP request with body.
|
||||
func PostJSON(url string, data []byte) (int, error) {
|
||||
req := pdk.NewHTTPRequest(pdk.MethodPost, url)
|
||||
req.SetHeader("Content-Type", "application/json")
|
||||
req.SetBody(data) // Works directly on stub
|
||||
|
||||
resp := req.Send() // This is mocked
|
||||
return int(resp.Status()), nil
|
||||
}
|
||||
|
||||
func TestPostJSON(t *testing.T) {
|
||||
pdk.ResetMock()
|
||||
|
||||
stubResponse := pdk.NewStubHTTPResponse(201, nil, nil)
|
||||
|
||||
pdk.PDKMock.On("NewHTTPRequest", pdk.MethodPost, "https://api.example.com/items").
|
||||
Return(&pdk.HTTPRequest{})
|
||||
pdk.PDKMock.On("Send", mock.AnythingOfType("*pdk.HTTPRequest")).
|
||||
Return(stubResponse)
|
||||
|
||||
status, err := PostJSON("https://api.example.com/items", []byte(`{"name":"test"}`))
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if status != 201 {
|
||||
t.Errorf("expected status 201, got %d", status)
|
||||
}
|
||||
|
||||
pdk.PDKMock.AssertExpectations(t)
|
||||
}
|
||||
204
plugins/pdk/go/pdk/pdk.go
Normal file
204
plugins/pdk/go/pdk/pdk.go
Normal file
@ -0,0 +1,204 @@
|
||||
// Code generated by ndpgen. DO NOT EDIT.
|
||||
//
|
||||
// This file contains wrapper functions for the extism/go-pdk package.
|
||||
// For WASM builds, it provides type aliases and function wrappers that delegate
|
||||
// to the real extism/go-pdk package with zero overhead.
|
||||
//
|
||||
//go:build wasip1
|
||||
|
||||
package pdk
|
||||
|
||||
import (
|
||||
extism "github.com/extism/go-pdk"
|
||||
)
|
||||
|
||||
// Type aliases - zero overhead, full compatibility
|
||||
type HTTPMethod = extism.HTTPMethod
|
||||
type HTTPRequest = extism.HTTPRequest
|
||||
type HTTPRequestMeta = extism.HTTPRequestMeta
|
||||
type HTTPResponse = extism.HTTPResponse
|
||||
type LogLevel = extism.LogLevel
|
||||
type Memory = extism.Memory
|
||||
|
||||
// Constants
|
||||
|
||||
const (
|
||||
LogDebug = extism.LogDebug
|
||||
LogError = extism.LogError
|
||||
LogInfo = extism.LogInfo
|
||||
LogTrace = extism.LogTrace
|
||||
LogWarn = extism.LogWarn
|
||||
)
|
||||
|
||||
const (
|
||||
MethodConnect = extism.MethodConnect
|
||||
MethodDelete = extism.MethodDelete
|
||||
MethodGet = extism.MethodGet
|
||||
MethodHead = extism.MethodHead
|
||||
MethodOptions = extism.MethodOptions
|
||||
MethodPatch = extism.MethodPatch
|
||||
MethodPost = extism.MethodPost
|
||||
MethodPut = extism.MethodPut
|
||||
MethodTrace = extism.MethodTrace
|
||||
)
|
||||
|
||||
// Functions
|
||||
func Allocate(length int) Memory {
|
||||
return extism.Allocate(length)
|
||||
}
|
||||
func AllocateBytes(data []byte) Memory {
|
||||
return extism.AllocateBytes(data)
|
||||
}
|
||||
|
||||
// AllocateJSON AllocateJSON allocates and saves the type `any` into Memory on the host.
|
||||
func AllocateJSON(v any) (Memory, error) {
|
||||
return extism.AllocateJSON(v)
|
||||
}
|
||||
|
||||
// AllocateString AllocateString allocates and saves the UTF-8 string `data` into Memory on the host.
|
||||
func AllocateString(data string) Memory {
|
||||
return extism.AllocateString(data)
|
||||
}
|
||||
|
||||
// FindMemory FindMemory finds the host memory block at the given `offset`.
|
||||
func FindMemory(offset uint64) Memory {
|
||||
return extism.FindMemory(offset)
|
||||
}
|
||||
|
||||
// GetConfig GetConfig returns the config string associated with `key` (if any).
|
||||
func GetConfig(key string) (string, bool) {
|
||||
return extism.GetConfig(key)
|
||||
}
|
||||
|
||||
// GetVar GetVar returns the byte slice (if any) associated with `key`.
|
||||
func GetVar(key string) []byte {
|
||||
return extism.GetVar(key)
|
||||
}
|
||||
|
||||
// GetVarInt GetVarInt returns the int associated with `key` (or 0 if none).
|
||||
func GetVarInt(key string) int {
|
||||
return extism.GetVarInt(key)
|
||||
}
|
||||
|
||||
// Input Input returns a slice of bytes from the host.
|
||||
func Input() []byte {
|
||||
return extism.Input()
|
||||
}
|
||||
|
||||
// InputJSON InputJSON returns unmartialed JSON data from the host "input".
|
||||
func InputJSON(v any) error {
|
||||
return extism.InputJSON(v)
|
||||
}
|
||||
|
||||
// InputString InputString returns the input data from the host as a UTF-8 string.
|
||||
func InputString() string {
|
||||
return extism.InputString()
|
||||
}
|
||||
|
||||
// JSONFrom JSONFrom unmarshals a `Memory` block located at `offset` from the host into the provided data `v`.
|
||||
func JSONFrom(offset uint64, v any) error {
|
||||
return extism.JSONFrom(offset, v)
|
||||
}
|
||||
|
||||
// Log Log logs the provided UTF-8 string `s` on the host using the provided log `level`.
|
||||
func Log(level LogLevel, s string) {
|
||||
extism.Log(level, s)
|
||||
}
|
||||
|
||||
// LogMemory LogMemory logs the `memory` block on the host using the provided log `level`.
|
||||
func LogMemory(level LogLevel, m Memory) {
|
||||
extism.LogMemory(level, m)
|
||||
}
|
||||
|
||||
// NewHTTPRequest NewHTTPRequest returns a new `HTTPRequest`.
|
||||
func NewHTTPRequest(method HTTPMethod, url string) *HTTPRequest {
|
||||
return extism.NewHTTPRequest(method, url)
|
||||
}
|
||||
func NewMemory(offset uint64, length uint64) Memory {
|
||||
return extism.NewMemory(offset, length)
|
||||
}
|
||||
|
||||
// Output Output sends the `data` slice of bytes to the host output.
|
||||
func Output(data []byte) {
|
||||
extism.Output(data)
|
||||
}
|
||||
|
||||
// OutputJSON OutputJSON marshals the provided data `v` as output to the host.
|
||||
func OutputJSON(v any) error {
|
||||
return extism.OutputJSON(v)
|
||||
}
|
||||
|
||||
// OutputMemory OutputMemory sends the `mem` Memory to the host output.
|
||||
func OutputMemory(mem Memory) {
|
||||
extism.OutputMemory(mem)
|
||||
}
|
||||
|
||||
// OutputString OutputString sends the UTF-8 string `s` to the host output.
|
||||
func OutputString(s string) {
|
||||
extism.OutputString(s)
|
||||
}
|
||||
|
||||
// ParamBytes ParamBytes returns bytes from Extism host memory given an offset.
|
||||
func ParamBytes(offset uint64) []byte {
|
||||
return extism.ParamBytes(offset)
|
||||
}
|
||||
|
||||
// ParamString ParamString returns UTF-8 string data from Extism host memory given an offset.
|
||||
func ParamString(offset uint64) string {
|
||||
return extism.ParamString(offset)
|
||||
}
|
||||
|
||||
// ParamU32 ParamU32 returns a uint32 from Extism host memory given an offset.
|
||||
func ParamU32(offset uint64) uint32 {
|
||||
return extism.ParamU32(offset)
|
||||
}
|
||||
|
||||
// ParamU64 ParamU64 returns a uint64 from Extism host memory given an offset.
|
||||
func ParamU64(offset uint64) uint64 {
|
||||
return extism.ParamU64(offset)
|
||||
}
|
||||
|
||||
// RemoveVar RemoveVar removes (and frees) the host variable associated with `key`.
|
||||
func RemoveVar(key string) {
|
||||
extism.RemoveVar(key)
|
||||
}
|
||||
|
||||
// ResultBytes ResultBytes allocates bytes and returns the offset in Extism host memory.
|
||||
func ResultBytes(d []byte) uint64 {
|
||||
return extism.ResultBytes(d)
|
||||
}
|
||||
|
||||
// ResultString ResultString allocates a UTF-8 string and returns the offset in Extism host memory.
|
||||
func ResultString(s string) uint64 {
|
||||
return extism.ResultString(s)
|
||||
}
|
||||
|
||||
// ResultU32 ResultU32 allocates a uint32 and returns the offset in Extism host memory.
|
||||
func ResultU32(d uint32) uint64 {
|
||||
return extism.ResultU32(d)
|
||||
}
|
||||
|
||||
// ResultU64 ResultU64 allocates a uint64 and returns the offset in Extism host memory.
|
||||
func ResultU64(d uint64) uint64 {
|
||||
return extism.ResultU64(d)
|
||||
}
|
||||
|
||||
// SetError SetError sets the host error string from `err`.
|
||||
func SetError(err error) {
|
||||
extism.SetError(err)
|
||||
}
|
||||
|
||||
// SetErrorString SetErrorString sets the host error string from `err`.
|
||||
func SetErrorString(err string) {
|
||||
extism.SetErrorString(err)
|
||||
}
|
||||
|
||||
// SetVar SetVar sets the host variable associated with `key` to the `value` byte slice.
|
||||
func SetVar(key string, value []byte) {
|
||||
extism.SetVar(key, value)
|
||||
}
|
||||
|
||||
// SetVarInt SetVarInt sets the host variable associated with `key` to the `value` int.
|
||||
func SetVarInt(key string, value int) {
|
||||
extism.SetVarInt(key, value)
|
||||
}
|
||||
210
plugins/pdk/go/pdk/pdk_stub.go
Normal file
210
plugins/pdk/go/pdk/pdk_stub.go
Normal file
@ -0,0 +1,210 @@
|
||||
// Code generated by ndpgen. DO NOT EDIT.
|
||||
//
|
||||
// This file contains mock implementations for non-WASM builds.
|
||||
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
|
||||
// Plugin authors can use the exported PDKMock instance to set expectations in tests.
|
||||
//
|
||||
//go:build !wasip1
|
||||
|
||||
package pdk
|
||||
|
||||
import "github.com/stretchr/testify/mock"
|
||||
|
||||
// MockPDK is the mock implementation for testing PDK functions.
|
||||
type MockPDK struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// PDKMock is the auto-instantiated mock instance for testing.
|
||||
// Use this to set expectations: pdk.PDKMock.On("GetConfig", "key").Return("value", true)
|
||||
var PDKMock = &MockPDK{}
|
||||
|
||||
// ResetMock resets the mock to its initial state.
|
||||
// Call this in test setup/teardown to ensure clean state between tests.
|
||||
func ResetMock() {
|
||||
PDKMock = &MockPDK{}
|
||||
}
|
||||
|
||||
// Functions
|
||||
func Allocate(length int) Memory {
|
||||
args := PDKMock.Called(length)
|
||||
return args.Get(0).(Memory)
|
||||
}
|
||||
func AllocateBytes(data []byte) Memory {
|
||||
args := PDKMock.Called(data)
|
||||
return args.Get(0).(Memory)
|
||||
}
|
||||
|
||||
// AllocateJSON AllocateJSON allocates and saves the type `any` into Memory on the host.
|
||||
func AllocateJSON(v any) (Memory, error) {
|
||||
args := PDKMock.Called(v)
|
||||
return args.Get(0).(Memory), args.Error(1)
|
||||
}
|
||||
|
||||
// AllocateString AllocateString allocates and saves the UTF-8 string `data` into Memory on the host.
|
||||
func AllocateString(data string) Memory {
|
||||
args := PDKMock.Called(data)
|
||||
return args.Get(0).(Memory)
|
||||
}
|
||||
|
||||
// FindMemory FindMemory finds the host memory block at the given `offset`.
|
||||
func FindMemory(offset uint64) Memory {
|
||||
args := PDKMock.Called(offset)
|
||||
return args.Get(0).(Memory)
|
||||
}
|
||||
|
||||
// GetConfig GetConfig returns the config string associated with `key` (if any).
|
||||
func GetConfig(key string) (string, bool) {
|
||||
args := PDKMock.Called(key)
|
||||
return args.String(0), args.Bool(1)
|
||||
}
|
||||
|
||||
// GetVar GetVar returns the byte slice (if any) associated with `key`.
|
||||
func GetVar(key string) []byte {
|
||||
args := PDKMock.Called(key)
|
||||
return args.Get(0).([]byte)
|
||||
}
|
||||
|
||||
// GetVarInt GetVarInt returns the int associated with `key` (or 0 if none).
|
||||
func GetVarInt(key string) int {
|
||||
args := PDKMock.Called(key)
|
||||
return args.Int(0)
|
||||
}
|
||||
|
||||
// Input Input returns a slice of bytes from the host.
|
||||
func Input() []byte {
|
||||
args := PDKMock.Called()
|
||||
return args.Get(0).([]byte)
|
||||
}
|
||||
|
||||
// InputJSON InputJSON returns unmartialed JSON data from the host "input".
|
||||
func InputJSON(v any) error {
|
||||
args := PDKMock.Called(v)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
// InputString InputString returns the input data from the host as a UTF-8 string.
|
||||
func InputString() string {
|
||||
args := PDKMock.Called()
|
||||
return args.String(0)
|
||||
}
|
||||
|
||||
// JSONFrom JSONFrom unmarshals a `Memory` block located at `offset` from the host into the provided data `v`.
|
||||
func JSONFrom(offset uint64, v any) error {
|
||||
args := PDKMock.Called(offset, v)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
// Log Log logs the provided UTF-8 string `s` on the host using the provided log `level`.
|
||||
func Log(level LogLevel, s string) {
|
||||
PDKMock.Called(level, s)
|
||||
}
|
||||
|
||||
// LogMemory LogMemory logs the `memory` block on the host using the provided log `level`.
|
||||
func LogMemory(level LogLevel, m Memory) {
|
||||
PDKMock.Called(level, m)
|
||||
}
|
||||
|
||||
// NewHTTPRequest NewHTTPRequest returns a new `HTTPRequest`.
|
||||
func NewHTTPRequest(method HTTPMethod, url string) *HTTPRequest {
|
||||
args := PDKMock.Called(method, url)
|
||||
return args.Get(0).(*HTTPRequest)
|
||||
}
|
||||
func NewMemory(offset uint64, length uint64) Memory {
|
||||
args := PDKMock.Called(offset, length)
|
||||
return args.Get(0).(Memory)
|
||||
}
|
||||
|
||||
// Output Output sends the `data` slice of bytes to the host output.
|
||||
func Output(data []byte) {
|
||||
PDKMock.Called(data)
|
||||
}
|
||||
|
||||
// OutputJSON OutputJSON marshals the provided data `v` as output to the host.
|
||||
func OutputJSON(v any) error {
|
||||
args := PDKMock.Called(v)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
// OutputMemory OutputMemory sends the `mem` Memory to the host output.
|
||||
func OutputMemory(mem Memory) {
|
||||
PDKMock.Called(mem)
|
||||
}
|
||||
|
||||
// OutputString OutputString sends the UTF-8 string `s` to the host output.
|
||||
func OutputString(s string) {
|
||||
PDKMock.Called(s)
|
||||
}
|
||||
|
||||
// ParamBytes ParamBytes returns bytes from Extism host memory given an offset.
|
||||
func ParamBytes(offset uint64) []byte {
|
||||
args := PDKMock.Called(offset)
|
||||
return args.Get(0).([]byte)
|
||||
}
|
||||
|
||||
// ParamString ParamString returns UTF-8 string data from Extism host memory given an offset.
|
||||
func ParamString(offset uint64) string {
|
||||
args := PDKMock.Called(offset)
|
||||
return args.String(0)
|
||||
}
|
||||
|
||||
// ParamU32 ParamU32 returns a uint32 from Extism host memory given an offset.
|
||||
func ParamU32(offset uint64) uint32 {
|
||||
args := PDKMock.Called(offset)
|
||||
return args.Get(0).(uint32)
|
||||
}
|
||||
|
||||
// ParamU64 ParamU64 returns a uint64 from Extism host memory given an offset.
|
||||
func ParamU64(offset uint64) uint64 {
|
||||
args := PDKMock.Called(offset)
|
||||
return args.Get(0).(uint64)
|
||||
}
|
||||
|
||||
// RemoveVar RemoveVar removes (and frees) the host variable associated with `key`.
|
||||
func RemoveVar(key string) {
|
||||
PDKMock.Called(key)
|
||||
}
|
||||
|
||||
// ResultBytes ResultBytes allocates bytes and returns the offset in Extism host memory.
|
||||
func ResultBytes(d []byte) uint64 {
|
||||
args := PDKMock.Called(d)
|
||||
return args.Get(0).(uint64)
|
||||
}
|
||||
|
||||
// ResultString ResultString allocates a UTF-8 string and returns the offset in Extism host memory.
|
||||
func ResultString(s string) uint64 {
|
||||
args := PDKMock.Called(s)
|
||||
return args.Get(0).(uint64)
|
||||
}
|
||||
|
||||
// ResultU32 ResultU32 allocates a uint32 and returns the offset in Extism host memory.
|
||||
func ResultU32(d uint32) uint64 {
|
||||
args := PDKMock.Called(d)
|
||||
return args.Get(0).(uint64)
|
||||
}
|
||||
|
||||
// ResultU64 ResultU64 allocates a uint64 and returns the offset in Extism host memory.
|
||||
func ResultU64(d uint64) uint64 {
|
||||
args := PDKMock.Called(d)
|
||||
return args.Get(0).(uint64)
|
||||
}
|
||||
|
||||
// SetError SetError sets the host error string from `err`.
|
||||
func SetError(err error) {
|
||||
PDKMock.Called(err)
|
||||
}
|
||||
|
||||
// SetErrorString SetErrorString sets the host error string from `err`.
|
||||
func SetErrorString(err string) {
|
||||
PDKMock.Called(err)
|
||||
}
|
||||
|
||||
// SetVar SetVar sets the host variable associated with `key` to the `value` byte slice.
|
||||
func SetVar(key string, value []byte) {
|
||||
PDKMock.Called(key, value)
|
||||
}
|
||||
|
||||
// SetVarInt SetVarInt sets the host variable associated with `key` to the `value` int.
|
||||
func SetVarInt(key string, value int) {
|
||||
PDKMock.Called(key, value)
|
||||
}
|
||||
192
plugins/pdk/go/pdk/types_stub.go
Normal file
192
plugins/pdk/go/pdk/types_stub.go
Normal file
@ -0,0 +1,192 @@
|
||||
// Code generated by ndpgen. DO NOT EDIT.
|
||||
//
|
||||
// This file contains type definitions for non-WASM builds.
|
||||
// These types match the extism/go-pdk signatures to allow compilation and testing
|
||||
// on native platforms without importing the WASM-only extism package.
|
||||
//
|
||||
//go:build !wasip1
|
||||
|
||||
package pdk
|
||||
|
||||
// LogLevel represents a logging level.
|
||||
type LogLevel int
|
||||
|
||||
// Log level constants
|
||||
const (
|
||||
LogTrace LogLevel = iota
|
||||
LogDebug
|
||||
LogInfo
|
||||
LogWarn
|
||||
LogError
|
||||
)
|
||||
|
||||
// HTTPMethod represents an HTTP method.
|
||||
type HTTPMethod int32
|
||||
|
||||
// HTTP method constants
|
||||
const (
|
||||
MethodGet HTTPMethod = iota
|
||||
MethodHead
|
||||
MethodPost
|
||||
MethodPut
|
||||
MethodPatch
|
||||
MethodDelete
|
||||
MethodConnect
|
||||
MethodOptions
|
||||
MethodTrace
|
||||
)
|
||||
|
||||
// String returns the string representation of the HTTP method.
|
||||
func (m HTTPMethod) String() string {
|
||||
switch m {
|
||||
case MethodGet:
|
||||
return "GET"
|
||||
case MethodHead:
|
||||
return "HEAD"
|
||||
case MethodPost:
|
||||
return "POST"
|
||||
case MethodPut:
|
||||
return "PUT"
|
||||
case MethodPatch:
|
||||
return "PATCH"
|
||||
case MethodDelete:
|
||||
return "DELETE"
|
||||
case MethodConnect:
|
||||
return "CONNECT"
|
||||
case MethodOptions:
|
||||
return "OPTIONS"
|
||||
case MethodTrace:
|
||||
return "TRACE"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
// Memory represents memory allocated by (and shared with) the host.
|
||||
// This is a stub implementation for non-WASM platforms.
|
||||
type Memory struct {
|
||||
offset uint64
|
||||
length uint64
|
||||
data []byte
|
||||
}
|
||||
|
||||
// Offset returns the offset of the memory block.
|
||||
func (m Memory) Offset() uint64 {
|
||||
return m.offset
|
||||
}
|
||||
|
||||
// Length returns the length of the memory block.
|
||||
func (m Memory) Length() uint64 {
|
||||
return m.length
|
||||
}
|
||||
|
||||
// ReadBytes reads all bytes from the memory block.
|
||||
func (m Memory) ReadBytes() []byte {
|
||||
return m.data
|
||||
}
|
||||
|
||||
// Load reads the memory block into the provided buffer.
|
||||
func (m *Memory) Load(buffer []byte) {
|
||||
copy(buffer, m.data)
|
||||
}
|
||||
|
||||
// Store writes data to the memory block.
|
||||
func (m *Memory) Store(data []byte) {
|
||||
m.data = make([]byte, len(data))
|
||||
copy(m.data, data)
|
||||
m.length = uint64(len(data))
|
||||
}
|
||||
|
||||
// Free frees the memory block.
|
||||
func (m *Memory) Free() {
|
||||
m.data = nil
|
||||
m.length = 0
|
||||
}
|
||||
|
||||
// NewStubMemory creates a new stub Memory for testing.
|
||||
// This is a helper function not present in the real PDK.
|
||||
func NewStubMemory(offset, length uint64, data []byte) Memory {
|
||||
return Memory{
|
||||
offset: offset,
|
||||
length: length,
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPRequest represents an HTTP request sent by the host.
|
||||
// This is a stub implementation for non-WASM platforms.
|
||||
type HTTPRequest struct {
|
||||
method HTTPMethod
|
||||
url string
|
||||
headers map[string]string
|
||||
body []byte
|
||||
}
|
||||
|
||||
// SetHeader sets an HTTP header key to value.
|
||||
func (r *HTTPRequest) SetHeader(key string, value string) *HTTPRequest {
|
||||
if r.headers == nil {
|
||||
r.headers = make(map[string]string)
|
||||
}
|
||||
r.headers[key] = value
|
||||
return r
|
||||
}
|
||||
|
||||
// SetBody sets the HTTP request body.
|
||||
func (r *HTTPRequest) SetBody(body []byte) *HTTPRequest {
|
||||
r.body = body
|
||||
return r
|
||||
}
|
||||
|
||||
// Send sends the HTTP request and returns the response.
|
||||
// In the stub implementation, this delegates to the mock.
|
||||
func (r *HTTPRequest) Send() HTTPResponse {
|
||||
args := PDKMock.Called(r)
|
||||
return args.Get(0).(HTTPResponse)
|
||||
}
|
||||
|
||||
// HTTPRequestMeta represents the metadata associated with an HTTP request.
|
||||
type HTTPRequestMeta struct {
|
||||
URL string `json:"url"`
|
||||
Method string `json:"method"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
}
|
||||
|
||||
// HTTPResponse represents an HTTP response returned from the host.
|
||||
// This is a stub implementation for non-WASM platforms.
|
||||
type HTTPResponse struct {
|
||||
status uint16
|
||||
headers map[string]string
|
||||
body []byte
|
||||
memory Memory
|
||||
}
|
||||
|
||||
// Status returns the status code from the response.
|
||||
func (r HTTPResponse) Status() uint16 {
|
||||
return r.status
|
||||
}
|
||||
|
||||
// Headers returns the HTTP response headers.
|
||||
func (r *HTTPResponse) Headers() map[string]string {
|
||||
return r.headers
|
||||
}
|
||||
|
||||
// Body returns the body byte slice from the response.
|
||||
func (r HTTPResponse) Body() []byte {
|
||||
return r.body
|
||||
}
|
||||
|
||||
// Memory returns the memory associated with the response.
|
||||
func (r HTTPResponse) Memory() Memory {
|
||||
return r.memory
|
||||
}
|
||||
|
||||
// NewStubHTTPResponse creates a new stub HTTPResponse for testing.
|
||||
// This is a helper function not present in the real PDK.
|
||||
func NewStubHTTPResponse(status uint16, headers map[string]string, body []byte) HTTPResponse {
|
||||
return HTTPResponse{
|
||||
status: status,
|
||||
headers: headers,
|
||||
body: body,
|
||||
memory: NewStubMemory(0, uint64(len(body)), body),
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// SchedulerCallbackRequest is the request provided when a scheduled task fires.
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
package scrobbler
|
||||
|
||||
import (
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// ScrobblerError represents an error type for scrobbling operations.
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// OnBinaryMessageRequest is the request provided when a binary message is received.
|
||||
|
||||
10
plugins/testdata/test-artwork/go.mod
vendored
10
plugins/testdata/test-artwork/go.mod
vendored
@ -2,9 +2,15 @@ module test-artwork
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
12
plugins/testdata/test-artwork/go.sum
vendored
12
plugins/testdata/test-artwork/go.sum
vendored
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
2
plugins/testdata/test-artwork/main.go
vendored
2
plugins/testdata/test-artwork/main.go
vendored
@ -5,8 +5,8 @@ package main
|
||||
import (
|
||||
"strings"
|
||||
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// TestInput is the input for nd_test_artwork callback.
|
||||
|
||||
10
plugins/testdata/test-cache-plugin/go.mod
vendored
10
plugins/testdata/test-cache-plugin/go.mod
vendored
@ -2,9 +2,15 @@ module test-cache-plugin
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
12
plugins/testdata/test-cache-plugin/go.sum
vendored
12
plugins/testdata/test-cache-plugin/go.sum
vendored
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
2
plugins/testdata/test-cache-plugin/main.go
vendored
2
plugins/testdata/test-cache-plugin/main.go
vendored
@ -3,8 +3,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// TestCacheInput is the input for nd_test_cache callback.
|
||||
|
||||
10
plugins/testdata/test-kvstore/go.mod
vendored
10
plugins/testdata/test-kvstore/go.mod
vendored
@ -2,9 +2,15 @@ module test-kvstore
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
12
plugins/testdata/test-kvstore/go.sum
vendored
12
plugins/testdata/test-kvstore/go.sum
vendored
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
2
plugins/testdata/test-kvstore/main.go
vendored
2
plugins/testdata/test-kvstore/main.go
vendored
@ -3,8 +3,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// TestKVStoreInput is the input for nd_test_kvstore callback.
|
||||
|
||||
10
plugins/testdata/test-library/go.mod
vendored
10
plugins/testdata/test-library/go.mod
vendored
@ -2,9 +2,15 @@ module test-library
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
12
plugins/testdata/test-library/go.sum
vendored
12
plugins/testdata/test-library/go.sum
vendored
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
2
plugins/testdata/test-library/main.go
vendored
2
plugins/testdata/test-library/main.go
vendored
@ -8,8 +8,8 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// TestLibraryInput is the input for nd_test_library callback.
|
||||
|
||||
10
plugins/testdata/test-metadata-agent/go.mod
vendored
10
plugins/testdata/test-metadata-agent/go.mod
vendored
@ -2,9 +2,15 @@ module test-metadata-agent
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
12
plugins/testdata/test-metadata-agent/go.sum
vendored
12
plugins/testdata/test-metadata-agent/go.sum
vendored
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
2
plugins/testdata/test-metadata-agent/main.go
vendored
2
plugins/testdata/test-metadata-agent/main.go
vendored
@ -6,8 +6,8 @@ import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/metadata"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
9
plugins/testdata/test-scheduler/go.mod
vendored
9
plugins/testdata/test-scheduler/go.mod
vendored
@ -4,6 +4,13 @@ go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require github.com/extism/go-pdk v1.1.3 // indirect
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
12
plugins/testdata/test-scheduler/go.sum
vendored
12
plugins/testdata/test-scheduler/go.sum
vendored
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
10
plugins/testdata/test-scrobbler/go.mod
vendored
10
plugins/testdata/test-scrobbler/go.mod
vendored
@ -2,9 +2,15 @@ module test-scrobbler
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
12
plugins/testdata/test-scrobbler/go.sum
vendored
12
plugins/testdata/test-scrobbler/go.sum
vendored
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
2
plugins/testdata/test-scrobbler/main.go
vendored
2
plugins/testdata/test-scrobbler/main.go
vendored
@ -6,7 +6,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/scrobbler"
|
||||
)
|
||||
|
||||
|
||||
10
plugins/testdata/test-subsonicapi-plugin/go.mod
vendored
10
plugins/testdata/test-subsonicapi-plugin/go.mod
vendored
@ -2,9 +2,15 @@ module test-subsonicapi-plugin
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
12
plugins/testdata/test-subsonicapi-plugin/go.sum
vendored
12
plugins/testdata/test-subsonicapi-plugin/go.sum
vendored
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
)
|
||||
|
||||
// call_subsonic_api is the exported function that tests the SubsonicAPI host function.
|
||||
|
||||
10
plugins/testdata/test-websocket/go.mod
vendored
10
plugins/testdata/test-websocket/go.mod
vendored
@ -2,9 +2,15 @@ module test-websocket
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/extism/go-pdk v1.1.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
12
plugins/testdata/test-websocket/go.sum
vendored
12
plugins/testdata/test-websocket/go.sum
vendored
@ -1,2 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
2
plugins/testdata/test-websocket/main.go
vendored
2
plugins/testdata/test-websocket/main.go
vendored
@ -5,8 +5,8 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
|
||||
pdk "github.com/extism/go-pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/websocket"
|
||||
)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user