Move database client into services package

This commit is contained in:
Tony Grosinger 2024-07-11 21:31:54 -07:00
parent bd54486fb3
commit 56383939ed
9 changed files with 24 additions and 30 deletions

View File

@ -12,7 +12,6 @@ import (
"git.grosinger.net/tgrosinger/saasitone/pkg/form" "git.grosinger.net/tgrosinger/saasitone/pkg/form"
"git.grosinger.net/tgrosinger/saasitone/pkg/log" "git.grosinger.net/tgrosinger/saasitone/pkg/log"
"git.grosinger.net/tgrosinger/saasitone/pkg/middleware" "git.grosinger.net/tgrosinger/saasitone/pkg/middleware"
"git.grosinger.net/tgrosinger/saasitone/pkg/models"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc" "git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/msg" "git.grosinger.net/tgrosinger/saasitone/pkg/msg"
"git.grosinger.net/tgrosinger/saasitone/pkg/page" "git.grosinger.net/tgrosinger/saasitone/pkg/page"
@ -38,7 +37,7 @@ type (
Auth struct { Auth struct {
auth *services.AuthClient auth *services.AuthClient
mail *services.MailClient mail *services.MailClient
db *models.Client db *services.DBClient
*services.TemplateRenderer *services.TemplateRenderer
} }

View File

@ -9,11 +9,11 @@ import (
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"git.grosinger.net/tgrosinger/saasitone/pkg/context" "git.grosinger.net/tgrosinger/saasitone/pkg/context"
"git.grosinger.net/tgrosinger/saasitone/pkg/models" "git.grosinger.net/tgrosinger/saasitone/pkg/services"
) )
// LoadUser loads the user based on the ID provided as a path parameter // LoadUser loads the user based on the ID provided as a path parameter
func LoadUser(db *models.Client) echo.MiddlewareFunc { func LoadUser(db *services.DBClient) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc { return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error { return func(c echo.Context) error {
userID, err := strconv.Atoi(c.Param("user")) userID, err := strconv.Atoi(c.Param("user"))

View File

@ -24,7 +24,7 @@ func TestMain(m *testing.M) {
// Create a user // Create a user
var err error var err error
if usr, err = tests.CreateUser(c.DB); err != nil { if usr, err = tests.CreateUser(c.DB.C); err != nil {
panic(err) panic(err)
} }

View File

@ -13,7 +13,6 @@ import (
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"git.grosinger.net/tgrosinger/saasitone/config" "git.grosinger.net/tgrosinger/saasitone/config"
"git.grosinger.net/tgrosinger/saasitone/pkg/models"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc" "git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/session" "git.grosinger.net/tgrosinger/saasitone/pkg/session"
) )
@ -48,11 +47,11 @@ func (e InvalidPasswordTokenError) Error() string {
// AuthClient is the client that handles authentication requests // AuthClient is the client that handles authentication requests
type AuthClient struct { type AuthClient struct {
config *config.Config config *config.Config
db *models.Client db *DBClient
} }
// NewAuthClient creates a new authentication client // NewAuthClient creates a new authentication client
func NewAuthClient(cfg *config.Config, db *models.Client) *AuthClient { func NewAuthClient(cfg *config.Config, db *DBClient) *AuthClient {
return &AuthClient{ return &AuthClient{
config: cfg, config: cfg,
db: db, db: db,

View File

@ -9,7 +9,6 @@ import (
"git.grosinger.net/tgrosinger/saasitone/config" "git.grosinger.net/tgrosinger/saasitone/config"
"git.grosinger.net/tgrosinger/saasitone/pkg/funcmap" "git.grosinger.net/tgrosinger/saasitone/pkg/funcmap"
"git.grosinger.net/tgrosinger/saasitone/pkg/models"
) )
// Container contains all services used by the application and provides an easy way to handle dependency // Container contains all services used by the application and provides an easy way to handle dependency
@ -28,7 +27,7 @@ type Container struct {
Cache *CacheClient Cache *CacheClient
// DB is the connection to the database and models for interacting with it // DB is the connection to the database and models for interacting with it
DB *models.Client DB *DBClient
// Mail stores an email sending client // Mail stores an email sending client
Mail *MailClient Mail *MailClient
@ -110,7 +109,7 @@ func (c *Container) initCache() {
// initDatabase initializes the database // initDatabase initializes the database
func (c *Container) initDatabase() { func (c *Container) initDatabase() {
client, err := models.New(c.Config) client, err := NewDBClient(c.Config)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -1,4 +1,4 @@
package models package services
import ( import (
"database/sql" "database/sql"
@ -13,16 +13,14 @@ import (
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc" "git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
) )
// TODO: Move this into services and have DBClient and NewDBClient type DBClient struct {
type Client struct {
db *sql.DB db *sql.DB
C *sqlc.Queries C *sqlc.Queries
User *UserClient User *DBUserClient
} }
func New(cfg *config.Config) (*Client, error) { func NewDBClient(cfg *config.Config) (*DBClient, error) {
logger := slog.Default() logger := slog.Default()
dbFilepath := cfg.Storage.DatabaseFile dbFilepath := cfg.Storage.DatabaseFile
@ -40,11 +38,11 @@ func New(cfg *config.Config) (*Client, error) {
return nil, err return nil, err
} }
client := Client{ client := DBClient{
db: db, db: db,
C: sqlc.New(db), C: sqlc.New(db),
} }
client.User = &UserClient{db: db} client.User = &DBUserClient{db: db}
migrationsDirPath := cfg.Storage.MigrationsDir migrationsDirPath := cfg.Storage.MigrationsDir
logger.Info("Loading schema migrations", logger.Info("Loading schema migrations",
@ -59,7 +57,7 @@ func New(cfg *config.Config) (*Client, error) {
// initSchema ensures that the database is current with the migrations contained // initSchema ensures that the database is current with the migrations contained
// in db/migrations. // in db/migrations.
func (c *Client) initSchema(migrationsDir string) error { func (c *DBClient) initSchema(migrationsDir string) error {
driver, err := sqlite3.WithInstance(c.db, &sqlite3.Config{}) driver, err := sqlite3.WithInstance(c.db, &sqlite3.Config{})
if err != nil { if err != nil {
return err return err
@ -85,7 +83,7 @@ func (c *Client) initSchema(migrationsDir string) error {
// WithTx executes the provided callback with access to a database transaction. // WithTx executes the provided callback with access to a database transaction.
// If the callback returns an error the transaction will be rolled back. // If the callback returns an error the transaction will be rolled back.
func (c *Client) WithTx(fn func(tx *sql.Tx) error) error { func (c *DBClient) WithTx(fn func(tx *sql.Tx) error) error {
tx, err := c.db.Begin() tx, err := c.db.Begin()
if err != nil { if err != nil {
return err return err
@ -100,7 +98,7 @@ func (c *Client) WithTx(fn func(tx *sql.Tx) error) error {
return tx.Commit() return tx.Commit()
} }
func (c *Client) WithSqlcTx(fn func(*sqlc.Queries) error) error { func (c *DBClient) WithSqlcTx(fn func(*sqlc.Queries) error) error {
return c.WithTx( return c.WithTx(
func(tx *sql.Tx) error { func(tx *sql.Tx) error {
return fn(c.C.WithTx(tx)) return fn(c.C.WithTx(tx))
@ -110,10 +108,10 @@ func (c *Client) WithSqlcTx(fn func(*sqlc.Queries) error) error {
// DB returns the underlying database object. Avoid whenever possible and use // DB returns the underlying database object. Avoid whenever possible and use
// either sqlc (preferred) or sub-clients. // either sqlc (preferred) or sub-clients.
func (c *Client) DB() *sql.DB { func (c *DBClient) DB() *sql.DB {
return c.db return c.db
} }
func (c *Client) Close() error { func (c *DBClient) Close() error {
return c.db.Close() return c.db.Close()
} }

View File

@ -30,7 +30,7 @@ func TestMain(m *testing.M) {
// Create a test user // Create a test user
var err error var err error
if usr, err = tests.CreateUser(c.DB); err != nil { if usr, err = tests.CreateUser(c.DB.C); err != nil {
panic(err) panic(err)
} }

View File

@ -1,9 +1,9 @@
package models package services
import "database/sql" import "database/sql"
// UserClient is a struct that can be used to create custom methods for // UserClient is a struct that can be used to create custom methods for
// interacting with users in the database. // interacting with users in the database.
type UserClient struct { type DBUserClient struct {
db *sql.DB db *sql.DB
} }

View File

@ -16,7 +16,6 @@ import (
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"git.grosinger.net/tgrosinger/saasitone/pkg/models"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc" "git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/session" "git.grosinger.net/tgrosinger/saasitone/pkg/session"
) )
@ -64,10 +63,10 @@ func AssertHTTPErrorCode(t *testing.T, err error, code int) {
} }
// CreateUser creates a random user entity // CreateUser creates a random user entity
func CreateUser(db *models.Client) (*sqlc.User, error) { func CreateUser(db *sqlc.Queries) (*sqlc.User, error) {
seed := fmt.Sprintf("%d-%d", time.Now().UnixMilli(), rand.Intn(1000000)) seed := fmt.Sprintf("%d-%d", time.Now().UnixMilli(), rand.Intn(1000000))
usr, err := db.C.CreateUser(context.Background(), sqlc.CreateUserParams{ usr, err := db.CreateUser(context.Background(), sqlc.CreateUserParams{
Name: fmt.Sprintf("Test User %s", seed), Name: fmt.Sprintf("Test User %s", seed),
Email: fmt.Sprintf("testuser-%s@localhost.localhost", seed), Email: fmt.Sprintf("testuser-%s@localhost.localhost", seed),
Password: "password", Password: "password",