108 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package store
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/asim/go-micro/v3/config"
 | |
| 	"github.com/asim/go-micro/v3/store"
 | |
| )
 | |
| 
 | |
| // NewConfig returns new config
 | |
| func NewConfig(store store.Store, key string) (config.Config, error) {
 | |
| 	return newConfig(store, key)
 | |
| }
 | |
| 
 | |
| type conf struct {
 | |
| 	key   string
 | |
| 	store store.Store
 | |
| }
 | |
| 
 | |
| func newConfig(store store.Store, key string) (*conf, error) {
 | |
| 	return &conf{
 | |
| 		store: store,
 | |
| 		key:   key,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| func (c *conf) Get(path string, options ...config.Option) (config.Value, error) {
 | |
| 	rec, err := c.store.Read(c.key)
 | |
| 	dat := []byte("{}")
 | |
| 	if err == nil && len(rec) > 0 {
 | |
| 		dat = rec[0].Value
 | |
| 	}
 | |
| 	values := config.NewJSONValues(dat)
 | |
| 	return values.Get(path), nil
 | |
| }
 | |
| 
 | |
| func (c *conf) Set(path string, val interface{}, options ...config.Option) error {
 | |
| 	rec, err := c.store.Read(c.key)
 | |
| 	dat := []byte("{}")
 | |
| 	if err == nil && len(rec) > 0 {
 | |
| 		dat = rec[0].Value
 | |
| 	}
 | |
| 	values := config.NewJSONValues(dat)
 | |
| 
 | |
| 	// marshal to JSON and back so we can iterate on the
 | |
| 	// value without reflection
 | |
| 	// @todo only do this if a struct
 | |
| 	JSON, err := json.Marshal(val)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	var v interface{}
 | |
| 	err = json.Unmarshal(JSON, &v)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	m, ok := v.(map[string]interface{})
 | |
| 	if ok {
 | |
| 		err := traverse(m, []string{path}, func(p string, value interface{}) error {
 | |
| 			values.Set(p, value)
 | |
| 			return nil
 | |
| 		})
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	} else {
 | |
| 		values.Set(path, val)
 | |
| 	}
 | |
| 	return c.store.Write(&store.Record{
 | |
| 		Key:   c.key,
 | |
| 		Value: values.Bytes(),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func traverse(m map[string]interface{}, paths []string, callback func(path string, value interface{}) error) error {
 | |
| 	for k, v := range m {
 | |
| 		val, ok := v.(map[string]interface{})
 | |
| 		if !ok {
 | |
| 			err := callback(strings.Join(append(paths, k), "."), v)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			continue
 | |
| 		}
 | |
| 		err := traverse(val, append(paths, k), callback)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (c *conf) Delete(path string, options ...config.Option) error {
 | |
| 	rec, err := c.store.Read(c.key)
 | |
| 	dat := []byte("{}")
 | |
| 	if err != nil || len(rec) == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 	values := config.NewJSONValues(dat)
 | |
| 	values.Delete(path)
 | |
| 	return c.store.Write(&store.Record{
 | |
| 		Key:   c.key,
 | |
| 		Value: values.Bytes(),
 | |
| 	})
 | |
| }
 |