package database import ( "bytes" "encoding/json" "os" "path/filepath" "go.jolheiser.com/vanity/sdk" "go.etcd.io/bbolt" ) var packageBucket = []byte("packages") type Database struct { db *bbolt.DB } func Load(dbPath string) (*Database, error) { if err := os.MkdirAll(filepath.Dir(dbPath), os.ModePerm); err != nil { return nil, err } db, err := bbolt.Open(dbPath, os.ModePerm, nil) if err != nil { return nil, err } return &Database{ db: db, }, db.Update(func(tx *bbolt.Tx) error { _, err := tx.CreateBucketIfNotExists(packageBucket) return err }) } func (d *Database) Package(name string) (sdk.Package, error) { var pkg sdk.Package data, err := d.PackageJSON(name) if err != nil { return pkg, err } return pkg, json.NewDecoder(bytes.NewReader(data)).Decode(&pkg) } func (d *Database) PackageJSON(name string) (pkg []byte, err error) { return pkg, d.db.View(func(tx *bbolt.Tx) error { pkg = tx.Bucket(packageBucket).Get([]byte(name)) if pkg == nil { return ErrPackageNotFound{ Name: name, } } return nil }) } func (d *Database) Packages() (pkgs []sdk.Package, err error) { return pkgs, d.db.View(func(tx *bbolt.Tx) error { return tx.Bucket(packageBucket).ForEach(func(key, val []byte) error { var pkg sdk.Package if err := json.NewDecoder(bytes.NewReader(val)).Decode(&pkg); err != nil { return err } pkgs = append(pkgs, pkg) return nil }) }) } func (d *Database) PutPackage(pkg sdk.Package) error { return d.db.Update(func(tx *bbolt.Tx) error { data, err := json.Marshal(pkg) if err != nil { return err } return tx.Bucket(packageBucket).Put([]byte(pkg.Name), data) }) } func (d *Database) RemovePackage(name string) error { return d.db.Update(func(tx *bbolt.Tx) error { return tx.Bucket(packageBucket).Delete([]byte(name)) }) }