A URL shortener service that uses ATProto to allow self hosting and ensuring the user owns their data
at main 1.4 kB view raw
1package database 2 3import ( 4 "database/sql" 5 "errors" 6 "fmt" 7 "log/slog" 8 "os" 9 10 _ "github.com/glebarez/go-sqlite" 11) 12 13type DB struct { 14 db *sql.DB 15} 16 17func New(dbPath string) (*DB, error) { 18 if dbPath != ":memory:" { 19 err := createDbFile(dbPath) 20 if err != nil { 21 return nil, fmt.Errorf("create db file: %w", err) 22 } 23 } 24 25 db, err := sql.Open("sqlite", dbPath) 26 if err != nil { 27 return nil, fmt.Errorf("open database: %w", err) 28 } 29 30 err = db.Ping() 31 if err != nil { 32 return nil, fmt.Errorf("ping db: %w", err) 33 } 34 35 err = createOauthRequestsTable(db) 36 if err != nil { 37 return nil, fmt.Errorf("creating oauth requests table: %w", err) 38 } 39 40 err = createOauthSessionsTable(db) 41 if err != nil { 42 return nil, fmt.Errorf("creating oauth sessions table: %w", err) 43 } 44 45 err = createURLsTable(db) 46 if err != nil { 47 return nil, fmt.Errorf("creating status table: %w", err) 48 } 49 err = createJetstreamTable(db) 50 if err != nil { 51 return nil, fmt.Errorf("creating jetstream table: %w", err) 52 } 53 54 return &DB{db: db}, nil 55} 56 57func (d *DB) Close() { 58 err := d.db.Close() 59 if err != nil { 60 slog.Error("failed to close db", "error", err) 61 } 62} 63 64func createDbFile(dbFilename string) error { 65 if _, err := os.Stat(dbFilename); !errors.Is(err, os.ErrNotExist) { 66 return nil 67 } 68 69 f, err := os.Create(dbFilename) 70 if err != nil { 71 return fmt.Errorf("create db file : %w", err) 72 } 73 f.Close() 74 return nil 75}