Files
sonr/internal/dwn/middleware/database.go
T
Prad NukalaandGitHub 8022428e37 feature/driver indexed db (#12)
* fix: update commitizen version

* feat: add WASM build tags to db actions

* feat: Update all actions to follow `AddAsset` for error handling

* feat: remove database dependency in dwn and motr commands

* feat: add basic info form to registration view

* feat: implement basic browser navigation component

* refactor: move database related files to middleware

* fix: remove unused test command

* fix: update source directory for buf-publish workflow
2024-09-16 01:06:00 -04:00

185 lines
3.7 KiB
Go

//go:build js && wasm
// +build js,wasm
package mdw
import (
"context"
"encoding/json"
"errors"
"syscall/js"
"github.com/hack-pad/go-indexeddb/idb"
)
type IndexedDBAPI interface{}
// Model is an interface that must be implemented by types used with Table
type Model interface {
Table() string
}
// Table is a generic wrapper around IDB for easier database operations on a specific table
type Table[T Model] struct {
db *idb.Database
dbName string
keyPath string
}
// NewTable creates a new Table instance
func NewTable[T Model](dbName string, version uint, keyPath string) (*Table[T], error) {
ctx := context.Background()
var model T
tableName := model.Table()
openRequest, err := idb.Global().Open(ctx, dbName, version, func(db *idb.Database, oldVersion, newVersion uint) error {
_, err := db.CreateObjectStore(tableName, idb.ObjectStoreOptions{
KeyPath: js.ValueOf(keyPath),
})
return err
})
if err != nil {
return nil, err
}
db, err := openRequest.Await(ctx)
if err != nil {
return nil, err
}
return &Table[T]{
db: db,
dbName: dbName,
keyPath: keyPath,
}, nil
}
// Insert adds a new record to the table
func (t *Table[T]) Insert(data T) error {
tx, err := t.db.Transaction(idb.TransactionReadWrite, data.Table())
if err != nil {
return err
}
defer tx.Commit()
objectStore, err := tx.ObjectStore(data.Table())
if err != nil {
return err
}
jsonData, err := json.Marshal(data)
if err != nil {
return err
}
_, err = objectStore.Add(js.ValueOf(string(jsonData)))
return err
}
// Query retrieves a record from the table based on a key
func (t *Table[T]) Query(key interface{}) (T, error) {
var result T
tx, err := t.db.Transaction(idb.TransactionReadOnly, result.Table())
if err != nil {
return result, err
}
defer tx.Commit()
objectStore, err := tx.ObjectStore(result.Table())
if err != nil {
return result, err
}
request, err := objectStore.Get(js.ValueOf(key))
if err != nil {
return result, err
}
value, err := request.Await(context.Background())
if err != nil {
return result, err
}
if value.IsUndefined() || value.IsNull() {
return result, errors.New("record not found")
}
err = json.Unmarshal([]byte(value.String()), &result)
return result, err
}
// First retrieves the first record from the table
func (t *Table[T]) First(data T) error {
tx, err := t.db.Transaction(idb.TransactionReadOnly, data.Table())
if err != nil {
return err
}
defer tx.Commit()
objectStore, err := tx.ObjectStore(data.Table())
if err != nil {
return err
}
request, err := objectStore.Get(js.ValueOf(t.keyPath))
if err != nil {
return err
}
value, err := request.Await(context.Background())
if err != nil {
return err
}
if value.IsUndefined() || value.IsNull() {
return errors.New("record not found")
}
err = json.Unmarshal([]byte(value.String()), &data)
return err
}
// Delete removes a record from the table based on a key
func (t *Table[T]) Delete(key interface{}) error {
var model T
tx, err := t.db.Transaction(idb.TransactionReadWrite, model.Table())
if err != nil {
return err
}
defer tx.Commit()
objectStore, err := tx.ObjectStore(model.Table())
if err != nil {
return err
}
_, err = objectStore.Delete(js.ValueOf(key))
return err
}
// Save updates a record in the table based on a key
func (t *Table[T]) Save(data T) error {
tx, err := t.db.Transaction(idb.TransactionReadWrite, data.Table())
if err != nil {
return err
}
defer tx.Commit()
objectStore, err := tx.ObjectStore(data.Table())
if err != nil {
return err
}
jsonData, err := json.Marshal(data)
if err != nil {
return err
}
_, err = objectStore.Put(js.ValueOf(string(jsonData)))
return err
}
// Close closes the database connection
func (t *Table[T]) Close() error {
return t.db.Close()
}