chore: refactor
This commit is contained in:
61
internal/console/console.go
Normal file
61
internal/console/console.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package console
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
)
|
||||
|
||||
type C[A any] struct {
|
||||
io.Reader
|
||||
io.Writer
|
||||
err io.Writer
|
||||
args A
|
||||
abort func()
|
||||
cancelfns []func(context.Context) error
|
||||
}
|
||||
|
||||
func New[A any](args A) (context.Context, *C[A]) {
|
||||
ctx := context.Background()
|
||||
ctx, abort := context.WithCancel(ctx)
|
||||
ctx, stop := signal.NotifyContext(ctx, os.Interrupt)
|
||||
go func() { <-ctx.Done(); stop() }() // restore interrupt function
|
||||
|
||||
console := &C[A]{Reader: os.Stdin, Writer: os.Stdout, err: os.Stderr, args: args, abort: abort}
|
||||
return ctx, console
|
||||
}
|
||||
|
||||
func (c *C[A]) Args() A {
|
||||
return c.args
|
||||
}
|
||||
func (c *C[A]) Shutdown() error {
|
||||
fmt.Fprintln(c.err, "shutting down ", len(c.cancelfns), " cancel functions...")
|
||||
defer fmt.Fprintln(c.err, "done")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
c.abort()
|
||||
var err error
|
||||
for _, fn := range c.cancelfns {
|
||||
err = errors.Join(err, fn(ctx))
|
||||
}
|
||||
return err
|
||||
}
|
||||
func (c *C[A]) AddCancel(fn func(context.Context) error) { c.cancelfns = append(c.cancelfns, fn) }
|
||||
|
||||
func (c *C[A]) IfFatal(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
fmt.Fprintln(c.err, err)
|
||||
err = c.Shutdown()
|
||||
if err != nil {
|
||||
fmt.Fprintln(c.err, err)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
54
internal/env/env.go
vendored
Normal file
54
internal/env/env.go
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
package env
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
||||
func Default(key, def string) string {
|
||||
if v, ok := os.LookupEnv(key); ok {
|
||||
return v
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
type secret struct {
|
||||
value string
|
||||
}
|
||||
func (s secret) Secret() string {
|
||||
return s.value
|
||||
}
|
||||
func (s secret) String() string {
|
||||
return "***"
|
||||
}
|
||||
func Secret(key, def string) secret {
|
||||
if v, ok := os.LookupEnv(key); ok {
|
||||
return secret{v}
|
||||
}
|
||||
return secret{def}
|
||||
}
|
||||
|
||||
func DotEnv() {
|
||||
fd, err := os.Open(".env")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
scan := bufio.NewScanner(fd)
|
||||
|
||||
for scan.Scan() {
|
||||
line := scan.Text()
|
||||
|
||||
if strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
key, val, ok := strings.Cut(line, "=")
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
os.Setenv(strings.TrimSpace(key), strings.TrimSpace(val))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user