Files
comicverse/comicverse.go

167 lines
3.6 KiB
Go
Raw Normal View History

2025-03-07 20:40:31 -03:00
package comicverse
import (
"context"
"database/sql"
"errors"
"io"
"io/fs"
"log/slog"
"net/http"
"forge.capytal.company/capytalcode/project-comicverse/assets"
"forge.capytal.company/capytalcode/project-comicverse/database"
"forge.capytal.company/capytalcode/project-comicverse/router"
"forge.capytal.company/capytalcode/project-comicverse/service"
2025-03-07 20:52:02 -03:00
"forge.capytal.company/capytalcode/project-comicverse/templates"
2025-03-07 20:40:31 -03:00
"forge.capytal.company/loreddev/x/tinyssert"
2025-03-11 09:46:03 -03:00
"github.com/aws/aws-sdk-go-v2/service/s3"
2025-03-07 20:40:31 -03:00
)
func New(cfg Config, opts ...Option) (http.Handler, error) {
app := &app{
db: cfg.DB,
s3: cfg.S3,
bucket: cfg.Bucket,
2025-03-11 09:46:03 -03:00
staticFiles: assets.Files(),
2025-03-07 20:40:31 -03:00
developmentMode: false,
ctx: context.Background(),
2025-03-07 20:40:31 -03:00
assert: tinyssert.NewAssertions(),
logger: slog.New(slog.NewTextHandler(io.Discard, &slog.HandlerOptions{Level: slog.LevelError})),
}
for _, opt := range opts {
opt(app)
}
if app.db == nil {
return nil, errors.New("database interface must not be nil")
}
2025-03-11 09:46:03 -03:00
if app.s3 == nil {
return nil, errors.New("s3 client must not be nil")
}
if app.bucket == "" {
return nil, errors.New("bucket must not be a empty string")
}
2025-03-11 09:46:03 -03:00
if app.staticFiles == nil {
return nil, errors.New("static files must not be a nil interface")
}
if app.ctx == nil {
2025-03-07 20:40:31 -03:00
return nil, errors.New("context must not be a nil interface")
}
if app.logger == nil {
return nil, errors.New("logger must not be a nil interface")
}
if app.assert == nil {
return nil, errors.New("assertions must not be a nil interface")
}
return app, app.setup()
}
type Config struct {
DB *sql.DB
S3 *s3.Client
Bucket string
2025-03-07 20:40:31 -03:00
}
type Option func(*app)
func WithContext(ctx context.Context) Option {
return func(app *app) { app.ctx = ctx }
2025-03-07 20:40:31 -03:00
}
func WithStaticFiles(f fs.FS) Option {
return func(app *app) { app.staticFiles = f }
}
func WithAssertions(a tinyssert.Assertions) Option {
return func(app *app) { app.assert = a }
}
func WithLogger(l *slog.Logger) Option {
return func(app *app) { app.logger = l }
}
func WithDevelopmentMode() Option {
return func(app *app) { app.developmentMode = true }
}
type app struct {
db *sql.DB
s3 *s3.Client
bucket string
2025-03-11 09:46:03 -03:00
ctx context.Context
staticFiles fs.FS
2025-03-07 20:40:31 -03:00
developmentMode bool
handler http.Handler
2025-03-07 20:40:31 -03:00
assert tinyssert.Assertions
logger *slog.Logger
}
func (app *app) setup() error {
app.assert.NotNil(app.db)
2025-03-11 09:46:03 -03:00
app.assert.NotNil(app.s3)
app.assert.NotZero(app.bucket)
app.assert.NotNil(app.ctx)
app.assert.NotNil(app.staticFiles)
2025-03-07 20:40:31 -03:00
app.assert.NotNil(app.logger)
var err error
database, err := database.New(database.Config{
SQL: app.db,
Context: app.ctx,
Assertions: app.assert,
2025-03-12 10:06:06 -03:00
Logger: app.logger.WithGroup("database"),
})
if err != nil {
return errors.Join(errors.New("unable to create database struct"), err)
}
service, err := service.New(service.Config{
DB: database,
S3: app.s3,
Bucket: app.bucket,
2025-03-11 09:57:10 -03:00
Context: app.ctx,
Assertions: app.assert,
2025-03-12 10:06:06 -03:00
Logger: app.logger.WithGroup("service"),
})
if err != nil {
return errors.Join(errors.New("unable to initiate service"), err)
}
app.handler, err = router.New(router.Config{
Service: service,
Templates: templates.Templates(),
DisableCache: app.developmentMode,
StaticFiles: app.staticFiles,
Assertions: app.assert,
2025-03-12 10:06:06 -03:00
Logger: app.logger.WithGroup("router"),
})
if err != nil {
return errors.Join(errors.New("unable to initiate router"), err)
}
2025-03-07 20:40:31 -03:00
return err
}
2025-03-07 20:40:31 -03:00
func (app *app) ServeHTTP(w http.ResponseWriter, r *http.Request) {
app.assert.NotNil(app.handler)
app.handler.ServeHTTP(w, r)
2025-03-07 20:40:31 -03:00
}