package storage import ( "fmt" "github.com/glebarez/sqlite" "gorm.io/driver/postgres" "gorm.io/gorm" ) // Storage is responsible for all database, cache and media related actions // and serves as the lowest layer of the cake type Storage struct { db *gorm.DB } // Build a new storage using sqlite as database backend func NewStorageSqlite(filePath string) (*Storage, error) { db, err := gorm.Open(sqlite.Open(filePath)) if err != nil { return nil, err } return storageFromEmptyDb(db) } func NewStoragePostgres(dbUrl string) (*Storage, error) { db, err := gorm.Open(postgres.Open(dbUrl)) if err != nil { return nil, err } return storageFromEmptyDb(db) } func storageFromEmptyDb(db *gorm.DB) (*Storage, error) { // AutoMigrate ensures the db is in a state where all the structs given here // have their own tables and relations setup. It also updates tables if necessary db.AutoMigrate( placeholderMediaFile, placeholderUser(), placeholderNote, placeholderServer, ) // Afterwards add the placeholder entries for each table. // FirstOrCreate either creates a new entry or retrieves the first matching one // We only care about the creation if there is none yet, so no need to carry the result over if res := db.FirstOrCreate(placeholderMediaFile); res.Error != nil { return nil, fmt.Errorf("failed to add placeholder media file: %w", res.Error) } if res := db.FirstOrCreate(placeholderUser()); res.Error != nil { return nil, fmt.Errorf("failed to add placeholder media file: %w", res.Error) } if res := db.FirstOrCreate(placeholderNote); res.Error != nil { return nil, fmt.Errorf("failed to add placeholder media file: %w", res.Error) } if res := db.FirstOrCreate(placeholderServer); res.Error != nil { return nil, fmt.Errorf("failed to add placeholder media file: %w", res.Error) } // And finally, build the actual storage struct return &Storage{ db: db, }, nil } // TODO: Placeholder. Update to proper implementation later. Including signature func (s *Storage) FindLocalAccount(handle string) (string, error) { return handle, nil }