add key processor
All checks were successful
Go Action / goaction (pull_request) Successful in 2m15s

This commit is contained in:
2026-01-01 19:33:45 +03:00
parent bb03532d83
commit 01d707ccbf
5 changed files with 132 additions and 6 deletions

View File

@@ -6,12 +6,13 @@ import (
"os"
"gitoa.ru/go-4devs/config"
"gitoa.ru/go-4devs/config/param"
"gitoa.ru/go-4devs/config/value"
)
var _ config.ProcessFunc = Env
func Env(_ context.Context, in config.Value) (config.Value, error) {
func Env(_ context.Context, in config.Value, _ ...param.Option) (config.Value, error) {
key, err := in.ParseString()
if err != nil {
return in, fmt.Errorf("process[env]:%w", err)

View File

@@ -0,0 +1,49 @@
package key
import (
"context"
"fmt"
"gitoa.ru/go-4devs/config"
"gitoa.ru/go-4devs/config/param"
"gitoa.ru/go-4devs/config/value"
)
type pkey int
const paramKey pkey = iota
func WithKey(in string) param.Option {
return func(p param.Params) param.Params {
return param.With(p, paramKey, in)
}
}
func Key(_ context.Context, in config.Value, opts ...param.Option) (config.Value, error) {
data := make(map[string]any, 0)
if err := in.Unmarshal(&data); err != nil {
return nil, fmt.Errorf("unmarshal:%w", err)
}
key, ok := getKey(opts...)
if !ok {
return nil, fmt.Errorf("key is %w", config.ErrRequired)
}
val, vok := data[key]
if !vok {
return nil, fmt.Errorf("value by key[%v]: %w", key, config.ErrNotFound)
}
return value.New(val), nil
}
func getKey(opts ...param.Option) (string, bool) {
params := param.New(opts...)
if name, ok := param.String(params, paramKey); ok {
return name, ok
}
return "", false
}

View File

@@ -0,0 +1,58 @@
package key_test
import (
"context"
"encoding/json"
"testing"
"gitoa.ru/go-4devs/config"
"gitoa.ru/go-4devs/config/processor/key"
"gitoa.ru/go-4devs/config/test/require"
"gitoa.ru/go-4devs/config/value"
)
func TestKey(t *testing.T) {
t.Parallel()
ctx := context.Background()
res, rerr := key.Key(ctx, keyData(t), key.WithKey("key"))
require.NoError(t, rerr)
require.Equal(t, "value", res.String())
}
func TestKey_required(t *testing.T) {
t.Parallel()
ctx := context.Background()
res, rerr := key.Key(ctx, keyData(t))
require.ErrorIs(t, rerr, config.ErrRequired)
require.Equal(t, res, nil)
}
func TestKey_notFound(t *testing.T) {
t.Parallel()
ctx := context.Background()
res, rerr := key.Key(ctx, keyData(t), key.WithKey("wrong"))
require.ErrorIs(t, rerr, config.ErrNotFound)
require.Equal(t, res, nil)
}
func keyData(t *testing.T) config.Value {
t.Helper()
data := map[string]string{
"key": "value",
}
jdata, err := json.Marshal(data)
require.NoError(t, err)
return value.JBytes(jdata)
}

View File

@@ -52,12 +52,12 @@ type Definition interface {
Add(opts ...Option)
}
type ProcessFunc func(ctx context.Context, in Value) (Value, error)
type ProcessFunc func(ctx context.Context, in Value, opts ...param.Option) (Value, error)
func (o ProcessFunc) Process(ctx context.Context, in Value) (Value, error) {
return o(ctx, in)
func (o ProcessFunc) Process(ctx context.Context, in Value, opts ...param.Option) (Value, error) {
return o(ctx, in, opts...)
}
type Processor interface {
Process(ctx context.Context, in Value) (Value, error)
Process(ctx context.Context, in Value, opts ...param.Option) (Value, error)
}

View File

@@ -15,13 +15,31 @@ const (
envSuffix = ")%"
)
func Env(parent config.Provider) EnvHandler {
type EnvOption func(*EnvHandler)
func WithEnvName(in string) EnvOption {
return func(eh *EnvHandler) {
eh.name = in
}
}
func WithEnvProcessor(proc config.Processor) EnvOption {
return func(eh *EnvHandler) {
eh.Processor = proc
}
}
func Env(parent config.Provider, opts ...EnvOption) EnvHandler {
handler := EnvHandler{
Provider: parent,
Processor: config.ProcessFunc(env.Env),
name: "env:" + parent.Name(),
}
for _, opt := range opts {
opt(&handler)
}
return handler
}