diff --git a/gen/sqlc/dbq/models.go b/gen/sqlc/dbq/models.go index a4344b5..bdff214 100644 --- a/gen/sqlc/dbq/models.go +++ b/gen/sqlc/dbq/models.go @@ -7,6 +7,7 @@ package dbq type Site struct { ID int64 Name string + Title string Url string Theme string Props []byte diff --git a/gen/sqlc/dbq/sites.sql.go b/gen/sqlc/dbq/sites.sql.go index 258befb..3aea488 100644 --- a/gen/sqlc/dbq/sites.sql.go +++ b/gen/sqlc/dbq/sites.sql.go @@ -9,8 +9,26 @@ import ( "context" ) +const getSiteWithID = `-- name: GetSiteWithID :one +SELECT id, name, title, url, theme, props FROM site WHERE id = $1 LIMIT 1 +` + +func (q *Queries) GetSiteWithID(ctx context.Context, id int64) (Site, error) { + row := q.db.QueryRow(ctx, getSiteWithID, id) + var i Site + err := row.Scan( + &i.ID, + &i.Name, + &i.Title, + &i.Url, + &i.Theme, + &i.Props, + ) + return i, err +} + const listSites = `-- name: ListSites :one -SELECT id, name, url, theme, props FROM site +SELECT id, name, title, url, theme, props FROM site ` func (q *Queries) ListSites(ctx context.Context) (Site, error) { @@ -19,6 +37,7 @@ func (q *Queries) ListSites(ctx context.Context) (Site, error) { err := row.Scan( &i.ID, &i.Name, + &i.Title, &i.Url, &i.Theme, &i.Props, @@ -29,15 +48,17 @@ func (q *Queries) ListSites(ctx context.Context) (Site, error) { const newSite = `-- name: NewSite :one INSERT INTO site ( name, + title, url, theme, props -) VALUES ($1, $2, $3, $4) +) VALUES ($1, $2, $3, $4, $5) RETURNING id ` type NewSiteParams struct { Name string + Title string Url string Theme string Props []byte @@ -46,6 +67,7 @@ type NewSiteParams struct { func (q *Queries) NewSite(ctx context.Context, arg NewSiteParams) (int64, error) { row := q.db.QueryRow(ctx, newSite, arg.Name, + arg.Title, arg.Url, arg.Theme, arg.Props, diff --git a/go.mod b/go.mod index dee3307..71910fe 100644 --- a/go.mod +++ b/go.mod @@ -8,14 +8,37 @@ require ( ) require ( + github.com/andybalholm/brotli v1.1.1 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/gofiber/fiber/v2 v2.52.6 // indirect + github.com/gofiber/fiber/v3 v3.0.0-beta.4 // indirect + github.com/gofiber/schema v1.2.0 // indirect + github.com/gofiber/template v1.8.3 // indirect + github.com/gofiber/template/html/v2 v2.1.3 // indirect + github.com/gofiber/utils v1.1.0 // indirect + github.com/gofiber/utils/v2 v2.0.0-beta.7 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/klauspost/compress v1.17.11 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/tinylib/msgp v1.2.5 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.58.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + github.com/x448/float16 v0.8.4 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/crypto v0.31.0 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/net v0.34.0 // indirect golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect ) diff --git a/go.sum b/go.sum index 29b6f37..7cbf0e1 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,27 @@ +github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= +github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI= +github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/gofiber/fiber/v3 v3.0.0-beta.4 h1:KzDSavvhG7m81NIsmnu5l3ZDbVS4feCidl4xlIfu6V0= +github.com/gofiber/fiber/v3 v3.0.0-beta.4/go.mod h1:/WFUoHRkZEsGHyy2+fYcdqi109IVOFbVwxv1n1RU+kk= +github.com/gofiber/schema v1.2.0 h1:j+ZRrNnUa/0ZuWrn/6kAtAufEr4jCJ+JuTURAMxNSZg= +github.com/gofiber/schema v1.2.0/go.mod h1:YYwj01w3hVfaNjhtJzaqetymL56VW642YS3qZPhuE6c= +github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc= +github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8= +github.com/gofiber/template/html/v2 v2.1.3 h1:n1LYBtmr9C0V/k/3qBblXyMxV5B0o/gpb6dFLp8ea+o= +github.com/gofiber/template/html/v2 v2.1.3/go.mod h1:U5Fxgc5KpyujU9OqKzy6Kn6Qup6Tm7zdsISR+VpnHRE= +github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM= +github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= +github.com/gofiber/utils/v2 v2.0.0-beta.7 h1:NnHFrRHvhrufPABdWajcKZejz9HnCWmT/asoxRsiEbQ= +github.com/gofiber/utils/v2 v2.0.0-beta.7/go.mod h1:J/M03s+HMdZdvhAeyh76xT72IfVqBzuz/OJkrMa7cwU= github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4CV3uAuvHGC+Y= github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -17,16 +37,46 @@ github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI= github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY= +github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po= +github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.58.0 h1:GGB2dWxSbEprU9j0iMJHgdKYJVDyjrOwF9RE59PbRuE= +github.com/valyala/fasthttp v1.58.0/go.mod h1:SYXvHHaFp7QZHGKSHmoMipInhrI5StHrhDTYVEjK/Kw= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/handlers/site.go b/handlers/site.go new file mode 100644 index 0000000..280c5f9 --- /dev/null +++ b/handlers/site.go @@ -0,0 +1,38 @@ +package handlers + +import ( + "fmt" + "github.com/gofiber/fiber/v2" + "lmika.dev/lmika/hugo-crm/services/sites" + "time" +) + +type Site struct { + Site *sites.Service +} + +func (s *Site) Create() fiber.Handler { + return func(c *fiber.Ctx) error { + site, err := s.Site.CreateSite(c.UserContext(), "New Site "+time.Now().Format("2006-01-02 15:04:05")) + if err != nil { + return err + } + + return c.Redirect(fmt.Sprintf("/sites/%v", site.ID)) + } +} + +func (s *Site) Show() fiber.Handler { + return func(c *fiber.Ctx) error { + id, err := c.ParamsInt("siteId") + if err != nil { + return err + } + + site, err := s.Site.GetSite(c.UserContext(), id) + + return c.Render("sites/index", fiber.Map{ + "site": site, + }, "layouts/main") + } +} diff --git a/main.go b/main.go index 36c9071..c8d5a0c 100644 --- a/main.go +++ b/main.go @@ -2,14 +2,20 @@ package main import ( "context" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/template/html/v2" "lmika.dev/lmika/hugo-crm/config" + "lmika.dev/lmika/hugo-crm/handlers" "lmika.dev/lmika/hugo-crm/providers/db" "lmika.dev/lmika/hugo-crm/providers/git" "lmika.dev/lmika/hugo-crm/providers/hugo" "lmika.dev/lmika/hugo-crm/providers/themes" + "lmika.dev/lmika/hugo-crm/services/jobs" + "lmika.dev/lmika/hugo-crm/services/sitebuilder" "lmika.dev/lmika/hugo-crm/services/sites" + "lmika.dev/lmika/hugo-crm/templates" "log" - "time" + "net/http" ) func main() { @@ -31,7 +37,12 @@ func main() { gitProvider := git.New() themesProvider := themes.New() - siteService := sites.NewService(cfg, dbp, themesProvider, gitProvider, hugoProvider) + jobService := jobs.New() + siteBuilderService := sitebuilder.New(themesProvider, gitProvider, hugoProvider) + + siteService := sites.NewService(cfg, dbp, themesProvider, siteBuilderService, jobService) + + siteHandlers := handlers.Site{Site: siteService} log.Println("Connected to database") if err := dbp.Migrate(context.Background()); err != nil { @@ -40,7 +51,24 @@ func main() { log.Println("Database migrated") - if _, err := siteService.CreateSite(context.Background(), "Test site "+time.Now().Format("2006-01-02T15:04:05")); err != nil { - log.Fatal(err) + tmplEngine := html.NewFileSystem(http.FS(templates.FS), ".html") + app := fiber.New(fiber.Config{ + Views: tmplEngine, + }) + + app.Get("/", func(c *fiber.Ctx) error { + return c.Render("index", fiber.Map{}, "layouts/main") + }) + + app.Post("/sites", siteHandlers.Create()) + app.Get("/sites/:siteId", siteHandlers.Show()) + + jobService.Start() + defer jobService.Stop() + + if err := app.Listen(":3000"); err != nil { + log.Println(err) } + + log.Println("Shutting down...") } diff --git a/models/job.go b/models/job.go new file mode 100644 index 0000000..c082b20 --- /dev/null +++ b/models/job.go @@ -0,0 +1,7 @@ +package models + +import "context" + +type Job struct { + Do func(ctx context.Context) error +} diff --git a/providers/db/sites.go b/providers/db/sites.go index e16b89d..e68d5f1 100644 --- a/providers/db/sites.go +++ b/providers/db/sites.go @@ -9,6 +9,7 @@ import ( func (db *DB) InsertSite(ctx context.Context, site *models.Site) error { id, err := db.q.NewSite(ctx, dbq.NewSiteParams{ Name: site.Name, + Title: site.Title, Url: site.URL, Theme: site.Theme, Props: []byte("{}"), @@ -19,3 +20,17 @@ func (db *DB) InsertSite(ctx context.Context, site *models.Site) error { site.ID = id return nil } + +func (db *DB) GetSite(ctx context.Context, id int64) (models.Site, error) { + site, err := db.q.GetSiteWithID(ctx, id) + if err != nil { + return models.Site{}, err + } + + return models.Site{ + ID: site.ID, + Name: site.Name, + Title: site.Title, + Theme: site.Theme, + }, nil +} diff --git a/services/jobs/services.go b/services/jobs/services.go new file mode 100644 index 0000000..ae3f3ac --- /dev/null +++ b/services/jobs/services.go @@ -0,0 +1,38 @@ +package jobs + +import ( + "context" + "lmika.dev/lmika/hugo-crm/models" + "log" +) + +type Service struct { + queue chan models.Job +} + +func New() *Service { + return &Service{ + queue: make(chan models.Job, 50), + } +} + +func (j *Service) Start() { + go func() { + for j := range j.queue { + if err := j.Do(context.Background()); err != nil { + log.Printf("job failed %v", err) + } + } + }() +} + +func (j *Service) Stop() { + q := j.queue + j.queue = nil + close(q) +} + +func (j *Service) Queue(ctx context.Context, job models.Job) error { + j.queue <- job + return nil +} diff --git a/services/sitebuilder/service.go b/services/sitebuilder/service.go new file mode 100644 index 0000000..39102a5 --- /dev/null +++ b/services/sitebuilder/service.go @@ -0,0 +1,57 @@ +package sitebuilder + +import ( + "context" + "errors" + "lmika.dev/lmika/hugo-crm/models" + "lmika.dev/lmika/hugo-crm/providers/git" + "lmika.dev/lmika/hugo-crm/providers/hugo" + "lmika.dev/lmika/hugo-crm/providers/themes" + "log" +) + +type Service struct { + themes *themes.Provider + git *git.Provider + hugo *hugo.Provider +} + +func New( + themes *themes.Provider, + git *git.Provider, + hugo *hugo.Provider, +) *Service { + return &Service{ + themes: themes, + git: git, + hugo: hugo, + } +} + +func (s *Service) CreateNewSite(site models.Site) models.Job { + return models.Job{ + Do: func(ctx context.Context) error { + themeMeta, ok := s.themes.Lookup(site.Theme) + if !ok { + return errors.New("theme not found") + } + + // Build the site + log.Printf(" .. build") + if err := s.hugo.NewSite(ctx, site); err != nil { + return err + } + + // Setup the theme + log.Printf(" .. theme") + if err := s.git.Clone(ctx, themeMeta.URL, s.hugo.SiteStagingDir(site, hugo.ThemeSiteDir)); err != nil { + return err + } + + if err := s.hugo.ReconfigureSite(ctx, site); err != nil { + return err + } + return nil + }, + } +} diff --git a/services/sites/service.go b/services/sites/service.go index 2c974f1..2c714dd 100644 --- a/services/sites/service.go +++ b/services/sites/service.go @@ -6,10 +6,9 @@ import ( "lmika.dev/lmika/hugo-crm/config" "lmika.dev/lmika/hugo-crm/models" "lmika.dev/lmika/hugo-crm/providers/db" - "lmika.dev/lmika/hugo-crm/providers/git" - "lmika.dev/lmika/hugo-crm/providers/hugo" "lmika.dev/lmika/hugo-crm/providers/themes" - "log" + "lmika.dev/lmika/hugo-crm/services/jobs" + "lmika.dev/lmika/hugo-crm/services/sitebuilder" "strings" "unicode" ) @@ -18,25 +17,30 @@ type Service struct { cfg config.Config db *db.DB themes *themes.Provider - git *git.Provider - hugo *hugo.Provider + sb *sitebuilder.Service + jobs *jobs.Service } func NewService( cfg config.Config, db *db.DB, themes *themes.Provider, - git *git.Provider, - hugo *hugo.Provider, + sb *sitebuilder.Service, + jobs *jobs.Service, ) *Service { return &Service{ - cfg: cfg, - db: db, - git: git, - hugo: hugo, + cfg: cfg, + db: db, + themes: themes, + sb: sb, + jobs: jobs, } } +func (s *Service) GetSite(ctx context.Context, id int) (models.Site, error) { + return s.db.GetSite(ctx, int64(id)) +} + func (s *Service) CreateSite(ctx context.Context, name string) (models.Site, error) { newSite := models.Site{ Name: normaliseName(name), @@ -44,7 +48,7 @@ func (s *Service) CreateSite(ctx context.Context, name string) (models.Site, err Theme: "bear", } - themeMeta, ok := s.themes.Lookup(newSite.Theme) + _, ok := s.themes.Lookup(newSite.Theme) if !ok { return models.Site{}, errors.New("theme not found") } @@ -53,23 +57,7 @@ func (s *Service) CreateSite(ctx context.Context, name string) (models.Site, err return models.Site{}, err } - // Build the site - log.Printf(" .. build") - if err := s.hugo.NewSite(ctx, newSite); err != nil { - return models.Site{}, err - } - - // Setup the theme - log.Printf(" .. theme") - if err := s.git.Clone(ctx, themeMeta.URL, s.hugo.SiteStagingDir(newSite, hugo.ThemeSiteDir)); err != nil { - return models.Site{}, err - } - - if err := s.hugo.ReconfigureSite(ctx, newSite); err != nil { - return models.Site{}, err - } - - return newSite, nil + return newSite, s.jobs.Queue(ctx, s.sb.CreateNewSite(newSite)) } func normaliseName(name string) string { diff --git a/sql/queries/sites.sql b/sql/queries/sites.sql index e1bc9df..d03f924 100644 --- a/sql/queries/sites.sql +++ b/sql/queries/sites.sql @@ -1,6 +1,9 @@ -- name: ListSites :one SELECT * FROM site; +-- name: GetSiteWithID :one +SELECT * FROM site WHERE id = $1 LIMIT 1; + -- name: NewSite :one INSERT INTO site ( name, diff --git a/sql/schema/1_init.up.sql b/sql/schema/1_init.up.sql index 537eafd..130583d 100644 --- a/sql/schema/1_init.up.sql +++ b/sql/schema/1_init.up.sql @@ -1,6 +1,7 @@ CREATE TABLE site ( id BIGSERIAL NOT NULL PRIMARY KEY, - name TEXT NOT NULL, + name TEXT NOT NULL UNIQUE, + title TEXT NOT NULL, url TEXT NOT NULL, theme TEXT NOT NULL, props JSON NOT NULL diff --git a/templates/fs.go b/templates/fs.go new file mode 100644 index 0000000..e2e8c6a --- /dev/null +++ b/templates/fs.go @@ -0,0 +1,8 @@ +package templates + +import "embed" + +//go:embed *.html +//go:embed layouts/*.html +//go:embed sites/*.html +var FS embed.FS diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..0c4d297 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,5 @@ +

Thing

+ +
+ +
diff --git a/templates/layouts/main.html b/templates/layouts/main.html new file mode 100644 index 0000000..d58d5d8 --- /dev/null +++ b/templates/layouts/main.html @@ -0,0 +1,9 @@ + + + + TEMP + + + {{embed}} + + \ No newline at end of file diff --git a/templates/sites/index.html b/templates/sites/index.html new file mode 100644 index 0000000..a87256f --- /dev/null +++ b/templates/sites/index.html @@ -0,0 +1 @@ +

Site {{.site.Title}}