andrey
9 months ago
7 changed files with 210 additions and 1 deletions
@ -0,0 +1,17 @@ |
|||
{ |
|||
"app": { |
|||
"name": { |
|||
"var": [ |
|||
"name" |
|||
], |
|||
"title": "config title", |
|||
"timeout": "1m", |
|||
"success": true |
|||
} |
|||
}, |
|||
"cfg": { |
|||
"duration": 1260000000000, |
|||
"enabled": true, |
|||
"type":"json" |
|||
} |
|||
} |
@ -0,0 +1,13 @@ |
|||
module gitoa.ru/go-4devs/config/provider/json |
|||
|
|||
go 1.21.5 |
|||
|
|||
require ( |
|||
github.com/tidwall/gjson v1.17.0 |
|||
gitoa.ru/go-4devs/config v0.0.1 |
|||
) |
|||
|
|||
require ( |
|||
github.com/tidwall/match v1.1.1 // indirect |
|||
github.com/tidwall/pretty v1.2.0 // indirect |
|||
) |
@ -0,0 +1,10 @@ |
|||
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= |
|||
github.com/tidwall/gjson v1.17.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.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= |
|||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= |
|||
gitoa.ru/go-4devs/config v0.0.0-20240125174937-085589a9383a h1:61iwpn1Ec4yIkBSvSz8knNENJuhj6v2rp6bfw1wkG0E= |
|||
gitoa.ru/go-4devs/config v0.0.0-20240125174937-085589a9383a/go.mod h1:3g2bwE2OTDyYwm33KN/Cqc8pEdGlWXnB8Ju3PsYNQr0= |
|||
gitoa.ru/go-4devs/config v0.0.1 h1:9KrOO09YbIMO8qL8aVn/G74DurGdOIW5y3O02bays4I= |
|||
gitoa.ru/go-4devs/config v0.0.1/go.mod h1:xfEC2Al9xnMLJUuekYs3KhJ5BIzWAseNwkMwbN6/xss= |
@ -0,0 +1,65 @@ |
|||
package json |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"os" |
|||
"path/filepath" |
|||
"strings" |
|||
|
|||
"github.com/tidwall/gjson" |
|||
"gitoa.ru/go-4devs/config" |
|||
"gitoa.ru/go-4devs/config/value" |
|||
) |
|||
|
|||
const ( |
|||
Name = "json" |
|||
Separator = "." |
|||
) |
|||
|
|||
var _ config.Provider = (*Provider)(nil) |
|||
|
|||
func New(json []byte, opts ...Option) *Provider { |
|||
provider := Provider{ |
|||
key: func(s ...string) string { |
|||
return strings.Join(s, Separator) |
|||
}, |
|||
data: json, |
|||
} |
|||
|
|||
for _, opt := range opts { |
|||
opt(&provider) |
|||
} |
|||
|
|||
return &provider |
|||
} |
|||
|
|||
func NewFile(path string, opts ...Option) (*Provider, error) { |
|||
file, err := os.ReadFile(filepath.Clean(path)) |
|||
if err != nil { |
|||
return nil, fmt.Errorf("%w: unable to read config file %#q: file not found or unreadable", err, path) |
|||
} |
|||
|
|||
return New(file, opts...), nil |
|||
} |
|||
|
|||
type Option func(*Provider) |
|||
|
|||
type Provider struct { |
|||
data []byte |
|||
key func(...string) string |
|||
name string |
|||
} |
|||
|
|||
func (p *Provider) Name() string { |
|||
return p.name |
|||
} |
|||
|
|||
func (p *Provider) Value(ctx context.Context, path ...string) (config.Value, error) { |
|||
key := p.key(path...) |
|||
if val := gjson.GetBytes(p.data, key); val.Exists() { |
|||
return value.JString(val.String()), nil |
|||
} |
|||
|
|||
return nil, fmt.Errorf("%v:%w", p.Name(), config.ErrValueNotFound) |
|||
} |
@ -0,0 +1,55 @@ |
|||
package json_test |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"log" |
|||
|
|||
"gitoa.ru/go-4devs/config" |
|||
"gitoa.ru/go-4devs/config/provider/json" |
|||
"gitoa.ru/go-4devs/config/test" |
|||
) |
|||
|
|||
func ExampleClient_Value() { |
|||
ctx := context.Background() |
|||
|
|||
// read json config
|
|||
jsonConfig, jerr := fixture.ReadFile("fixture/config.json") |
|||
if jerr != nil { |
|||
log.Printf("failed load file:%v", jerr) |
|||
|
|||
return |
|||
} |
|||
|
|||
config, err := config.New( |
|||
json.New(jsonConfig), |
|||
) |
|||
if err != nil { |
|||
log.Print(err) |
|||
|
|||
return |
|||
} |
|||
|
|||
title, err := config.Value(ctx, "app.name.title") |
|||
if err != nil { |
|||
log.Print("app.name.title", err) |
|||
|
|||
return |
|||
} |
|||
|
|||
cfgValue, err := config.Value(ctx, "cfg") |
|||
if err != nil { |
|||
log.Print("cfg ", err) |
|||
|
|||
return |
|||
} |
|||
|
|||
cfg := test.Config{} |
|||
_ = cfgValue.Unmarshal(&cfg) |
|||
|
|||
fmt.Printf("title from json: %v\n", title.String()) |
|||
fmt.Printf("struct from json: %+v\n", cfg) |
|||
// Output:
|
|||
// title from json: config title
|
|||
// struct from json: {Duration:21m0s Enabled:true}
|
|||
} |
@ -0,0 +1,33 @@ |
|||
package json_test |
|||
|
|||
import ( |
|||
"embed" |
|||
"testing" |
|||
"time" |
|||
|
|||
"gitoa.ru/go-4devs/config/provider/json" |
|||
"gitoa.ru/go-4devs/config/test" |
|||
"gitoa.ru/go-4devs/config/test/require" |
|||
) |
|||
|
|||
//go:embed fixture/*
|
|||
var fixture embed.FS |
|||
|
|||
func TestProvider(t *testing.T) { |
|||
t.Parallel() |
|||
|
|||
js, err := fixture.ReadFile("fixture/config.json") |
|||
require.NoError(t, err) |
|||
|
|||
prov := json.New(js) |
|||
sl := []string{} |
|||
read := []test.Read{ |
|||
test.NewRead("config title", "app.name.title"), |
|||
test.NewRead(time.Minute, "app.name.timeout"), |
|||
test.NewReadUnmarshal(&[]string{"name"}, &sl, "app.name.var"), |
|||
test.NewReadConfig("cfg"), |
|||
test.NewRead(true, "app", "name", "success"), |
|||
} |
|||
|
|||
test.Run(t, prov, read) |
|||
} |
Loading…
Reference in new issue