initial wip
This commit is contained in:
commit
d01ea2d78e
12 changed files with 316 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
blas
|
||||
Session.vim
|
||||
coverage.txt
|
6
Makefile
Normal file
6
Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
all: build
|
||||
build:
|
||||
go build -o blas ./cmd/blas/
|
||||
|
||||
debug:
|
||||
dlv debug ./cmd/blas/ ${ARGS}
|
12
go.mod
Normal file
12
go.mod
Normal file
|
@ -0,0 +1,12 @@
|
|||
module dynatron.me/x/blasphem
|
||||
|
||||
go 1.18
|
||||
|
||||
require github.com/spf13/cobra v1.5.0
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
14
go.sum
Normal file
14
go.sum
Normal file
|
@ -0,0 +1,14 @@
|
|||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
31
internal/common/common.go
Normal file
31
internal/common/common.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
AppName = "blasphem"
|
||||
)
|
||||
|
||||
type cmdOptions interface {
|
||||
Options(*cobra.Command, []string) error
|
||||
Execute() error
|
||||
}
|
||||
|
||||
func RunE(c cmdOptions) func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
err := c.Options(cmd, args)
|
||||
if err != nil {
|
||||
cmd.SilenceUsage = true
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.Execute()
|
||||
if err != nil {
|
||||
cmd.SilenceUsage = true
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
14
pkg/bus/bus.go
Normal file
14
pkg/bus/bus.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package bus
|
||||
|
||||
import (
|
||||
)
|
||||
|
||||
type Bus struct {
|
||||
}
|
||||
|
||||
func New() *Bus {
|
||||
bus := &Bus{
|
||||
}
|
||||
|
||||
return bus
|
||||
}
|
48
pkg/cmd/serve/cmd.go
Normal file
48
pkg/cmd/serve/cmd.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
package serve
|
||||
|
||||
import (
|
||||
"dynatron.me/x/blasphem/internal/common"
|
||||
"dynatron.me/x/blasphem/pkg/config"
|
||||
"dynatron.me/x/blasphem/pkg/server"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type ServeOptions struct {
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func Command(cfg *config.Config) *cobra.Command {
|
||||
opts := makeOptions(cfg)
|
||||
serveCmd := &cobra.Command{
|
||||
Use: "serve",
|
||||
Short: "starts the " + common.AppName + " server",
|
||||
RunE: common.RunE(opts),
|
||||
}
|
||||
|
||||
return serveCmd
|
||||
}
|
||||
|
||||
func makeOptions(cfg *config.Config) *ServeOptions {
|
||||
return &ServeOptions{
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ServeOptions) Options(_ *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *ServeOptions) Execute() error {
|
||||
server, err := server.New(o.cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = server.Go()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
77
pkg/config/config.go
Normal file
77
pkg/config/config.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
server "dynatron.me/x/blasphem/pkg/server/config"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server *server.Config `yaml:"server"`
|
||||
}
|
||||
|
||||
const (
|
||||
IncludeTag = "!include"
|
||||
IncludeDirNamedTag = "!include_dir_named"
|
||||
IncludeDirListTag = "!include_dir_list"
|
||||
IncludeDirMergeNamedTag = "!include_dir_merge_named"
|
||||
SecretTag = "!secret"
|
||||
)
|
||||
|
||||
func (c *Config) UnmarshalYAML(y *yaml.Node) error {
|
||||
if y.Kind != yaml.MappingNode {
|
||||
return yerr(y, errors.New("config root must be a map"))
|
||||
}
|
||||
|
||||
cV := reflect.ValueOf(c).Elem()
|
||||
|
||||
components := make(map[string]reflect.Value, cV.NumField())
|
||||
for i := 0; i < cV.NumField(); i++ {
|
||||
if tag, ok := cV.Type().Field(i).Tag.Lookup("yaml"); ok {
|
||||
tags := strings.Split(tag, ",")
|
||||
components[tags[0]] = cV.Field(i)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(y.Content); i += 2 {
|
||||
k, v := y.Content[i], y.Content[i+1]
|
||||
|
||||
switch v.LongTag() {
|
||||
case IncludeTag:
|
||||
fallthrough
|
||||
case IncludeDirNamedTag:
|
||||
fallthrough
|
||||
case IncludeDirMergeNamedTag:
|
||||
fallthrough
|
||||
case SecretTag:
|
||||
panic(fmt.Errorf("tag %s not implemented", v.LongTag()))
|
||||
default:
|
||||
var key string
|
||||
err := k.Decode(&key)
|
||||
if err != nil {
|
||||
return yerr(y, err)
|
||||
}
|
||||
|
||||
if comp, ok := components[key]; ok {
|
||||
val := reflect.New(comp.Type())
|
||||
err := v.Decode(val.Interface())
|
||||
if err != nil {
|
||||
return yerr(y, err)
|
||||
}
|
||||
|
||||
comp.Set(val.Elem())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func yerr(y *yaml.Node, ye error) error {
|
||||
return fmt.Errorf("line %d: %w", y.Line, ye)
|
||||
}
|
39
pkg/config/read.go
Normal file
39
pkg/config/read.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"dynatron.me/x/blasphem/internal/common"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func ReadConfig() (*Config, error) {
|
||||
cfg := &Config{}
|
||||
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfgPath := path.Join(home, "/." + common.AppName, "/config.yaml")
|
||||
|
||||
r, err := os.Open(cfgPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfgB, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(cfgB, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
5
pkg/server/config/config.go
Normal file
5
pkg/server/config/config.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package config
|
||||
|
||||
type Config struct {
|
||||
Bind string `yaml:"bind"`
|
||||
}
|
50
pkg/server/server.go
Normal file
50
pkg/server/server.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"dynatron.me/x/blasphem/pkg/bus"
|
||||
"dynatron.me/x/blasphem/pkg/config"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
*bus.Bus
|
||||
*http.Server
|
||||
wg sync.WaitGroup
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func New(cfg *config.Config) (*Server, error) {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
s := &Server{
|
||||
Bus: bus.New(),
|
||||
Server: &http.Server{
|
||||
Addr: cfg.Server.Bind,
|
||||
Handler: mux,
|
||||
},
|
||||
cfg: cfg,
|
||||
}
|
||||
|
||||
mux.HandleFunc("/api/websocket", s.wsHandler)
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *Server) Go() error {
|
||||
s.wg.Add(1)
|
||||
go func() {
|
||||
err := s.ListenAndServe()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
s.wg.Done()
|
||||
}()
|
||||
|
||||
s.wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
17
pkg/server/websocket.go
Normal file
17
pkg/server/websocket.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
|
||||
func (s *Server) wsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
//conn, err := upgrader.Upgrade(w, req, nil)
|
||||
panic("not implemented")
|
||||
}
|
Loading…
Reference in a new issue