Compare commits

..

13 Commits

Author SHA1 Message Date
Joel Wetzell
1d4cb251e9 switch to WebMIDI driver when building JS 2026-03-30 15:16:35 -05:00
Joel Wetzell
050ada6a70 mess around with support WASM builds 2026-03-30 14:46:35 -05:00
Joel Wetzell
882af2948a fix JSON schema of net.udp.server 2026-03-26 18:56:03 -05:00
Joel Wetzell
e2e9fb5eb6 add other methods to http request schema 2026-03-26 18:20:02 -05:00
Joel Wetzell
411888d8db align schema of udp server with reality 2026-03-26 15:13:26 -05:00
Joel Wetzell
e367d6eb5d Merge pull request #120 from jwetzell/dependabot/go_modules/github.com/nats-io/nats-server/v2-2.12.6
Bump github.com/nats-io/nats-server/v2 from 2.12.5 to 2.12.6
2026-03-26 15:05:19 -05:00
Joel Wetzell
7659f412fb Delete .github/workflows/label-pr.yaml 2026-03-26 15:04:33 -05:00
Joel Wetzell
85964f5e25 Delete .github/labeler.yml 2026-03-26 15:04:25 -05:00
dependabot[bot]
b9e8bb66c6 Bump github.com/nats-io/nats-server/v2 from 2.12.5 to 2.12.6
Bumps [github.com/nats-io/nats-server/v2](https://github.com/nats-io/nats-server) from 2.12.5 to 2.12.6.
- [Release notes](https://github.com/nats-io/nats-server/releases)
- [Changelog](https://github.com/nats-io/nats-server/blob/main/RELEASES.md)
- [Commits](https://github.com/nats-io/nats-server/compare/v2.12.5...v2.12.6)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats-server/v2
  dependency-version: 2.12.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-24 17:26:08 +00:00
Joel Wetzell
2f9ca82b81 add redis to protocols 2026-03-23 20:47:27 -05:00
Joel Wetzell
25579cb941 update cmd help 2026-03-23 20:42:02 -05:00
Joel Wetzell
9134f034c7 Merge pull request #119 from jwetzell/feat/env-vars-cmd-config
add support for sourcing flags from ENV vars
2026-03-23 20:40:25 -05:00
Joel Wetzell
204ccab683 add support for sourcing flags from ENV vars 2026-03-23 20:39:02 -05:00
45 changed files with 497 additions and 87 deletions

27
.github/labeler.yml vendored
View File

@@ -1,27 +0,0 @@
config:
- changed-files:
- any-glob-to-any-file: "internal/config/**"
framer:
- changed-files:
- any-glob-to-any-file: "internal/framer/**"
module:
- changed-files:
- any-glob-to-any-file: "internal/module/**"
processor:
- changed-files:
- any-glob-to-any-file: "internal/processor/**"
router:
- changed-files:
- any-glob-to-any-file: "router*"
route:
- changed-files:
- any-glob-to-any-file: "internal/route/**"
cli:
- changed-files:
- any-glob-to-any-file: "cmd/showbridge/**"

View File

@@ -1,18 +0,0 @@
# Taken from https://github.com/go-gitea/gitea
name: Add labels to PR
on:
pull_request_target:
types: [opened, synchronize, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
labeler:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
with:
sync-labels: true

View File

@@ -25,6 +25,7 @@ Simple protocol router _/s_
- [OSC](https://opensoundcontrol.stanford.edu/spec-1_0.html)
- [FreeD](https://ptzoptics.com/freed/)
- [SIP](https://en.wikipedia.org/wiki/Session_Initiation_Protocol)
- [Redis](https://redis.io/)
### CLI Usage
@@ -36,9 +37,10 @@ USAGE:
showbridge [global options]
GLOBAL OPTIONS:
--config string path to config file (default: "./config.yaml")
--log-level string set log level (default: "info")
--log-format string log format to use (default: "text")
--config string path to config file (default: "./config.yaml") [$SHOWBRIDGE_CONFIG]
--log-level string set log level (default: "info") [$SHOWBRIDGE_LOG_LEVEL]
--log-format string log format to use (default: "text") [$SHOWBRIDGE_LOG_FORMAT]
--trace enable OpenTelemetry tracing [$SHOWBRIDGE_TRACE]
--help, -h show help
--version, -v print the version
```

5
app/demo/document.go Normal file
View File

@@ -0,0 +1,5 @@
package main
import "syscall/js"
var document = js.Global().Get("document")

71
app/demo/index.html Normal file
View File

@@ -0,0 +1,71 @@
<html>
<head>
<meta charset="utf-8" />
<script src="wasm_exec.js"></script>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
height: 100vh;
margin: 0;
padding: 0;
}
#output-container {
flex-grow: 1;
}
#log-container {
background-color: #1e1e1e;
width: 100%;
height: 200px;
overflow-y: auto;
overflow-x: scroll;
box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.5);
}
#logs {
margin: 0;
padding-left: 2px;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 13px;
line-height: 1.4;
color: #a8cc8c;
}
</style>
<script>
const container = document.getElementById("log-container");
function isScrolledToBottom() {
const scrollThreshold = 1;
return (
container.scrollHeight - container.clientHeight <=
container.scrollTop + scrollThreshold
);
}
function scrollToBottomManual() {
const container = document.getElementById("log-container");
// Set scrollTop to the maximum value possible (scrollHeight - clientHeight)
container.scrollTop = container.scrollHeight - container.clientHeight;
}
</script>
</head>
<body>
<div id="output-container">
<div id="output"></div>
</div>
<div id="log-container">
<pre id="logs"></pre>
</div>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(
fetch("main.wasm"),
go.importObject,
).then((result) => {
go.run(result.instance);
});
</script>
</body>
</html>

42
app/demo/log.go Normal file
View File

@@ -0,0 +1,42 @@
package main
import "syscall/js"
type LogWriter struct {
Element js.Value
Container js.Value
}
func (pw *LogWriter) ScrollToBottom() {
scrollHeight := pw.Container.Get("scrollHeight").Int()
clientHeight := pw.Container.Get("clientHeight").Int()
pw.Container.Set("scrollTop", scrollHeight-clientHeight)
}
func (pw *LogWriter) IsScrolledToBottom() bool {
scrollHeight := pw.Container.Get("scrollHeight").Int()
clientHeight := pw.Container.Get("clientHeight").Int()
scrollTop := pw.Container.Get("scrollTop").Int()
return scrollHeight-clientHeight <= scrollTop+25
}
func (pw *LogWriter) Write(p []byte) (n int, err error) {
if !pw.Element.IsUndefined() {
currentText := pw.Element.Get("textContent").String()
newText := currentText + string(p)
pw.Element.Set("textContent", newText)
if pw.IsScrolledToBottom() {
pw.ScrollToBottom()
}
}
return len(p), nil
}
func NewLogWriter(id string) *LogWriter {
element := document.Call("getElementById", id)
container := element.Get("parentElement")
return &LogWriter{
Element: element,
Container: container,
}
}

71
app/demo/main.go Normal file
View File

@@ -0,0 +1,71 @@
package main
import (
"context"
"fmt"
"log/slog"
"github.com/jwetzell/showbridge-go"
"github.com/jwetzell/showbridge-go/internal/config"
)
func main() {
slog.SetLogLoggerLevel(slog.LevelDebug)
slog.SetDefault(slog.New(slog.NewTextHandler(NewLogWriter("logs"), &slog.HandlerOptions{
Level: slog.LevelDebug,
})))
router, moduleConfigErrors, routeConfigErrors := showbridge.NewRouter(config.Config{
Api: config.ApiConfig{
Enabled: false,
Port: 0,
},
Modules: []config.ModuleConfig{
{
Id: "midi",
Type: "midi.input",
Params: map[string]any{
"port": "Launchpad S",
},
},
},
Routes: []config.RouteConfig{
{
Input: "midi",
Processors: []config.ProcessorConfig{
{
Type: "debug.log",
},
{
Type: "web.set",
Params: map[string]any{
"id": "output",
"property": "textContent",
"value": "{{.Payload}}",
},
},
},
},
},
})
if len(moduleConfigErrors) > 0 {
for _, err := range moduleConfigErrors {
println("Module config error:", err.Error)
}
}
if len(routeConfigErrors) > 0 {
for _, err := range routeConfigErrors {
println("Route config error:", err.Error)
}
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
router.Start(ctx)
fmt.Println("router stopped")
}()
<-ctx.Done()
}

View File

@@ -38,9 +38,10 @@ func main() {
Version: version,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config",
Value: "./config.yaml",
Usage: "path to config file",
Name: "config",
Value: "./config.yaml",
Usage: "path to config file",
Sources: cli.EnvVars("SHOWBRIDGE_CONFIG"),
},
&cli.StringFlag{
Name: "log-level",
@@ -53,6 +54,7 @@ func main() {
}
return nil
},
Sources: cli.EnvVars("SHOWBRIDGE_LOG_LEVEL"),
},
&cli.StringFlag{
Name: "log-format",
@@ -65,11 +67,13 @@ func main() {
}
return nil
},
Sources: cli.EnvVars("SHOWBRIDGE_LOG_FORMAT"),
},
&cli.BoolFlag{
Name: "trace",
Value: false,
Usage: "enable OpenTelemetry tracing",
Name: "trace",
Value: false,
Usage: "enable OpenTelemetry tracing",
Sources: cli.EnvVars("SHOWBRIDGE_TRACE"),
},
},
Action: run,

10
go.mod
View File

@@ -14,7 +14,7 @@ require (
github.com/jwetzell/free-d-go v0.1.0
github.com/jwetzell/osc-go v0.2.0
github.com/jwetzell/psn-go v0.3.0
github.com/nats-io/nats-server/v2 v2.12.5
github.com/nats-io/nats-server/v2 v2.12.6
github.com/nats-io/nats.go v1.49.0
github.com/redis/go-redis/v9 v9.18.0
github.com/urfave/cli/v3 v3.7.0
@@ -53,7 +53,7 @@ require (
github.com/klauspost/compress v1.18.4 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 // indirect
github.com/nats-io/jwt/v2 v2.8.0 // indirect
github.com/nats-io/jwt/v2 v2.8.1 // indirect
github.com/nats-io/nkeys v0.4.15 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
@@ -74,11 +74,11 @@ require (
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.34.0 // indirect
golang.org/x/text v0.35.0 // indirect
golang.org/x/time v0.15.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect

20
go.sum
View File

@@ -87,10 +87,10 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk=
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g=
github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
github.com/nats-io/nats-server/v2 v2.12.5 h1:EOHLbsLJgUHUwzkj9gBTOlubkX+dmSs0EYWMdBiHivU=
github.com/nats-io/nats-server/v2 v2.12.5/go.mod h1:JQDAKcwdXs0NRhvYO31dzsXkzCyDkOBS7SKU3Nozu14=
github.com/nats-io/jwt/v2 v2.8.1 h1:V0xpGuD/N8Mi+fQNDynXohVvp7ZztevW5io8CUWlPmU=
github.com/nats-io/jwt/v2 v2.8.1/go.mod h1:nWnOEEiVMiKHQpnAy4eXlizVEtSfzacZ1Q43LIRavZg=
github.com/nats-io/nats-server/v2 v2.12.6 h1:Egbx9Vl7Ch8wTtpXPGqbehkZ+IncKqShUxvrt1+Enc8=
github.com/nats-io/nats-server/v2 v2.12.6/go.mod h1:4HPlrvtmSO3yd7KcElDNMx9kv5EBJBnJJzQPptXlheo=
github.com/nats-io/nats.go v1.49.0 h1:yh/WvY59gXqYpgl33ZI+XoVPKyut/IcEaqtsiuTJpoE=
github.com/nats-io/nats.go v1.49.0/go.mod h1:fDCn3mN5cY8HooHwE2ukiLb4p4G4ImmzvXyJt+tGwdw=
github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4=
@@ -163,20 +163,20 @@ go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
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/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
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/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -0,0 +1,7 @@
//go:build cgo
package module
import (
_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
)

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,4 +1,4 @@
//go:build cgo
//go:build cgo || js
package module
@@ -12,7 +12,6 @@ import (
"github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config"
"gitlab.com/gomidi/midi/v2"
_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
)
type MIDIInput struct {

View File

@@ -1,4 +1,4 @@
//go:build cgo
//go:build cgo || js
package module
@@ -12,7 +12,6 @@ import (
"github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config"
"gitlab.com/gomidi/midi/v2"
_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
)
type MIDIOutput struct {

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -64,7 +64,7 @@ func (t *TimeTimer) Start(ctx context.Context) error {
router, ok := ctx.Value(common.RouterContextKey).(common.RouteIO)
if !ok {
return errors.New("net.tcp.client unable to get router from context")
return errors.New("time.timer unable to get router from context")
}
t.router = router
moduleContext, cancel := context.WithCancel(ctx)

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package module
import (

View File

@@ -1,7 +1,10 @@
//go:build !js
package module
import (
"context"
"encoding/json"
"errors"
"fmt"
"log/slog"
@@ -31,8 +34,9 @@ func init() {
Type: "object",
Properties: map[string]*jsonschema.Schema{
"ip": {
Title: "IP",
Type: "string",
Title: "IP",
Type: "string",
Default: json.RawMessage(`"0.0.0.0"`),
},
"port": {
Title: "Port",
@@ -40,8 +44,15 @@ func init() {
Minimum: jsonschema.Ptr[float64](1024),
Maximum: jsonschema.Ptr[float64](65535),
},
"bufferSize": {
Title: "Buffer Size",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1),
Maximum: jsonschema.Ptr[float64](65535),
Default: json.RawMessage("2048"),
},
},
Required: []string{"ip", "port"},
Required: []string{"port"},
AdditionalProperties: nil,
},
New: func(moduleConfig config.ModuleConfig) (common.Module, error) {

View File

@@ -0,0 +1,91 @@
//go:build js
package module
import (
"context"
"errors"
"fmt"
"log/slog"
"syscall/js"
"time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config"
)
type WebOnClick struct {
config config.ModuleConfig
ctx context.Context
router common.RouteIO
logger *slog.Logger
ElementId string
}
func init() {
RegisterModule(ModuleRegistration{
Type: "web.onclick",
Title: "On Click",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"id": {
Title: "Element ID",
Type: "string",
Description: "ID of the HTML element to attach the click listener to",
},
},
Required: []string{"duration"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params
idString, err := params.GetString("id")
if err != nil {
return nil, fmt.Errorf("web.onclick id error: %w", err)
}
return &WebOnClick{ElementId: idString, config: config, logger: CreateLogger(config)}, nil
},
})
}
func (woc *WebOnClick) Id() string {
return woc.config.Id
}
func (woc *WebOnClick) Type() string {
return woc.config.Type
}
func (woc *WebOnClick) Start(ctx context.Context) error {
woc.logger.Debug("running")
router, ok := ctx.Value(common.RouterContextKey).(common.RouteIO)
if !ok {
return errors.New("net.tcp.client unable to get router from context")
}
woc.router = router
woc.ctx = ctx
element := js.Global().Get("document").Call("getElementById", woc.ElementId)
if element.IsNull() || element.IsUndefined() {
return fmt.Errorf("web.onclick unable to find element with id: %s", woc.ElementId)
}
element.Set("onclick", js.FuncOf(func(js.Value, []js.Value) interface{} {
if woc.router != nil {
woc.router.HandleInput(woc.ctx, woc.Id(), time.Now())
}
return nil
}))
<-ctx.Done()
return nil
}
func (woc *WebOnClick) Stop() {
}

7
internal/module/web.go Normal file
View File

@@ -0,0 +1,7 @@
//go:build js
package module
import (
_ "gitlab.com/gomidi/midi/v2/drivers/webmididrv"
)

View File

@@ -1,3 +1,5 @@
//go:build !js
package processor
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package processor
import (

View File

@@ -21,6 +21,11 @@ type HTTPRequestDo struct {
URL *template.Template
}
type HTTPResponse struct {
Status int
Body []byte
}
func (hrd *HTTPRequestDo) Process(ctx context.Context, wrappedPayload common.WrappedPayload) (common.WrappedPayload, error) {
templateData := wrappedPayload
@@ -79,7 +84,7 @@ func init() {
"method": {
Title: "HTTP Method",
Type: "string",
Enum: []any{"GET", "POST"},
Enum: []any{"GET", "POST", "PUT", "PATCH", "DELETE"},
},
"url": {
Title: "URL",

View File

@@ -1,3 +1,5 @@
//go:build !js
package processor
import (
@@ -17,11 +19,6 @@ type HTTPResponseCreate struct {
config config.ProcessorConfig
}
type HTTPResponse struct {
Status int
Body []byte
}
func (hrc *HTTPResponseCreate) Process(ctx context.Context, wrappedPayload common.WrappedPayload) (common.WrappedPayload, error) {
templateData := wrappedPayload

View File

@@ -1,4 +1,4 @@
//go:build cgo
//go:build cgo || js
package processor

View File

@@ -1,4 +1,4 @@
//go:build cgo
//go:build cgo || js
package processor

View File

@@ -1,4 +1,4 @@
//go:build cgo
//go:build cgo || js
package processor

View File

@@ -1,4 +1,4 @@
//go:build cgo
//go:build cgo || js
package processor

View File

@@ -1,3 +1,5 @@
//go:build !js
package processor
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package processor
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package processor
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package processor
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package processor
import (

View File

@@ -1,3 +1,5 @@
//go:build !js
package processor
import (

View File

@@ -0,0 +1,102 @@
//go:build js
package processor
import (
"bytes"
"context"
"fmt"
"html/template"
"log/slog"
"syscall/js"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config"
)
type WebSet struct {
config config.ProcessorConfig
ModuleId string
ElementId string
Property string
Value *template.Template
logger *slog.Logger
}
func (kvs *WebSet) Process(ctx context.Context, wrappedPayload common.WrappedPayload) (common.WrappedPayload, error) {
element := js.Global().Get("document").Call("getElementById", kvs.ElementId)
if element.IsNull() || element.IsUndefined() {
wrappedPayload.End = true
return wrappedPayload, fmt.Errorf("web.set unable to find element with id: %s", kvs.ElementId)
}
var valueBuffer bytes.Buffer
err := kvs.Value.Execute(&valueBuffer, wrappedPayload)
if err != nil {
wrappedPayload.End = true
return wrappedPayload, err
}
element.Set(kvs.Property, valueBuffer.String())
return wrappedPayload, nil
}
func (kvs *WebSet) Type() string {
return kvs.config.Type
}
func init() {
RegisterProcessor(ProcessorRegistration{
Type: "web.set",
Title: "Set Web Element Property",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"id": {
Title: "Element ID",
Type: "string",
},
"property": {
Title: "Property",
Type: "string",
},
"value": {
Title: "Value",
Type: "string",
},
},
Required: []string{"id", "property", "value"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params
idString, err := params.GetString("id")
if err != nil {
return nil, fmt.Errorf("web.set id error: %w", err)
}
propertyString, err := params.GetString("property")
if err != nil {
return nil, fmt.Errorf("web.set property error: %w", err)
}
valueString, err := params.GetString("value")
if err != nil {
return nil, fmt.Errorf("web.set value error: %w", err)
}
valueTemplate, err := template.New("template").Parse(valueString)
if err != nil {
return nil, err
}
return &WebSet{config: config, ElementId: idString, Property: propertyString, Value: valueTemplate, logger: slog.Default().With("component", "processor", "type", config.Type)}, nil
},
})
}