5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-11 14:39:30 +08:00
wails/v3/pkg/services/kvstore/kvstore.go
Atterpac e316cd0719
[V3] Plugins implemenations (#3570)
* plugin handler and lifecycle

* rebase

* remove reflect

s

* remove Config and NewPlugin from plugin template

* Remove plugin manager, generation of plugin interface

* implement http handlers for services

remove log

trim path

prefix wails/services

* update plugine example

* Misc updates

* Ported plugins to services, rewritten example

* Added fileserver

* Update OnStartup and use a context for the application

* Rename PathPrefix to Route. Create docs.

* Use service config copy. Add Name to Service Options. Improve service generation.

* Use service config copy. Add Name to Service Options. Improve service generation. Update README

* Remove rogue db

* Update changelog.md

---------

Co-authored-by: Lea O'Anthony <lea.anthony@gmail.com>
2024-09-01 17:26:22 +10:00

162 lines
3.0 KiB
Go

package kvstore
import (
"context"
"encoding/json"
"io"
"os"
"sync"
"github.com/pkg/errors"
"github.com/wailsapp/wails/v3/pkg/application"
)
type KeyValueStore struct {
config *Config
filename string
data map[string]any
unsaved bool
lock sync.RWMutex
}
type Config struct {
Filename string
AutoSave bool
}
type Service struct{}
func New(config *Config) *KeyValueStore {
return &KeyValueStore{
config: config,
data: make(map[string]any),
}
}
// OnShutdown will save the store to disk if there are unsaved changes.
func (kvs *KeyValueStore) OnShutdown() error {
if kvs.unsaved {
err := kvs.Save()
if err != nil {
return errors.Wrap(err, "Error saving store")
}
}
return nil
}
// Name returns the name of the plugin.
func (kvs *KeyValueStore) Name() string {
return "github.com/wailsapp/wails/v3/plugins/kvstore"
}
// OnStartup is called when the plugin is loaded. This is where you should do any setup.
func (kvs *KeyValueStore) OnStartup(ctx context.Context, options application.ServiceOptions) error {
err := kvs.open(kvs.config.Filename)
if err != nil {
return err
}
return nil
}
func (kvs *KeyValueStore) open(filename string) (err error) {
kvs.filename = filename
kvs.data = make(map[string]any)
file, err := os.Open(filename)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
defer func() {
err2 := file.Close()
if err2 != nil {
application.Get().Logger.Error("Key/Value Store Plugin Error:", "error", err.Error())
if err == nil {
err = err2
}
}
}()
bytes, err := io.ReadAll(file)
if err != nil {
return err
}
if len(bytes) > 0 {
if err := json.Unmarshal(bytes, &kvs.data); err != nil {
return err
}
}
return nil
}
// Save saves the store to disk
func (kvs *KeyValueStore) Save() error {
kvs.lock.Lock()
defer kvs.lock.Unlock()
bytes, err := json.Marshal(kvs.data)
if err != nil {
return err
}
err = os.WriteFile(kvs.filename, bytes, 0644)
if err != nil {
return err
}
kvs.unsaved = false
return nil
}
// Get returns the value for the given key. If key is empty, the entire store is returned.
func (kvs *KeyValueStore) Get(key string) any {
kvs.lock.RLock()
defer kvs.lock.RUnlock()
if key == "" {
return kvs.data
}
return kvs.data[key]
}
// Set sets the value for the given key. If AutoSave is true, the store is saved to disk.
func (kvs *KeyValueStore) Set(key string, value any) error {
kvs.lock.Lock()
kvs.data[key] = value
kvs.lock.Unlock()
if kvs.config.AutoSave {
err := kvs.Save()
if err != nil {
return err
}
kvs.unsaved = false
} else {
kvs.unsaved = true
}
return nil
}
// Delete deletes the key from the store. If AutoSave is true, the store is saved to disk.
func (kvs *KeyValueStore) Delete(key string) error {
kvs.lock.Lock()
delete(kvs.data, key)
kvs.lock.Unlock()
if kvs.config.AutoSave {
err := kvs.Save()
if err != nil {
return err
}
kvs.unsaved = false
} else {
kvs.unsaved = true
}
return nil
}