// Package models defines the data models used by the chat application. // All model structs embed Base, which provides database access for // relation-fetching methods directly on model instances. package models import ( "context" "database/sql" "errors" ) // DB is the interface that models use to query the database. // This avoids a circular import with the db package. type DB interface { GetDB() *sql.DB } // UserLookup provides user lookup by ID without circular imports. type UserLookup interface { GetUserByID(ctx context.Context, id string) (*User, error) } // ChannelLookup provides channel lookup by ID without circular imports. type ChannelLookup interface { GetChannelByID(ctx context.Context, id string) (*Channel, error) } // Sentinel errors for model lookup methods. var ( ErrUserLookupNotAvailable = errors.New("user lookup not available") ErrChannelLookupNotAvailable = errors.New("channel lookup not available") ) // Base is embedded in all model structs to provide database access. type Base struct { db DB } // SetDB injects the database reference into a model. func (b *Base) SetDB(d DB) { b.db = d } // GetDB returns the database interface for use in model methods. func (b *Base) GetDB() *sql.DB { return b.db.GetDB() } // GetUserLookup returns the DB as a UserLookup if it implements the interface. func (b *Base) GetUserLookup() UserLookup { //nolint:ireturn // interface return is intentional if ul, ok := b.db.(UserLookup); ok { return ul } return nil } // GetChannelLookup returns the DB as a ChannelLookup if it implements the interface. func (b *Base) GetChannelLookup() ChannelLookup { //nolint:ireturn // interface return is intentional if cl, ok := b.db.(ChannelLookup); ok { return cl } return nil }