diff --git a/adapters/secondary/gateways/articleRepository.go b/adapters/secondary/gateways/articleRepository.go index 058df17..fd2a7f6 100644 --- a/adapters/secondary/gateways/articleRepository.go +++ b/adapters/secondary/gateways/articleRepository.go @@ -18,9 +18,24 @@ func NewArticleRepository() *ArticleRepository { return &a } +func (a *ArticleRepository) connectClient() { + err := a.client.Connect() + if err != nil { + panic(err) + } +} + +func (a *ArticleRepository) disconnectClient() { + err := a.client.Disconnect() + if err != nil { + panic(err) + } + a.client = db.NewClient() +} + func (a *ArticleRepository) Get(id int) Article { - a.client.Connect() - defer a.client.Disconnect() + a.connectClient() + defer a.disconnectClient() article, err := a.client.Article.FindUnique(db.Article.ID.Equals(id)).Exec(context.Background()) if err != nil { @@ -31,8 +46,8 @@ func (a *ArticleRepository) Get(id int) Article { } func (a *ArticleRepository) Create(article Article) Article { - a.client.Connect() - defer a.client.Disconnect() + a.connectClient() + defer a.disconnectClient() articleDb, err := a.client.Article.CreateOne( db.Article.Title.Set(article.Title), @@ -45,4 +60,21 @@ func (a *ArticleRepository) Create(article Article) Article { return FromDb(articleDb.ID, articleDb.Title, articleDb.Body, articleDb.CreatedAt.String(), articleDb.UpdatedAt.String()) } +func (a *ArticleRepository) GetAll() []Article { + a.connectClient() + defer a.disconnectClient() + + articlesDb, err := a.client.Article.FindMany().Exec(context.Background()) + if err != nil { + panic(err) + } + + var articles []Article + for _, articleDb := range articlesDb { + articles = append(articles, FromDb(articleDb.ID, articleDb.Title, articleDb.Body, articleDb.CreatedAt.String(), articleDb.UpdatedAt.String())) + } + + return articles +} + var _ IArticleRepository = &ArticleRepository{} diff --git a/api/article.go b/api/article.go index 851d876..82b29bf 100644 --- a/api/article.go +++ b/api/article.go @@ -3,12 +3,57 @@ package api import ( . "GohCMS2/domain/article" . "GohCMS2/useCases" + "encoding/json" + "github.com/go-chi/chi/v5" + "net/http" + "strconv" ) -func GetArticle(id int) Article { - return container.GetArticleUseCase.GetArticle(id) +func getArticle(w http.ResponseWriter, r *http.Request) { + id, err := strconv.Atoi(chi.URLParam(r, "id")) + if err != nil { + http.Error(w, err.Error(), http.StatusNotFound) + return + } + + article := container.GetArticleUseCase.GetArticle(id) + articleJson, err := json.Marshal(article) + if err != nil { + http.Error(w, err.Error(), http.StatusNotFound) + return + } + + _, _ = w.Write(articleJson) } -func CreateArticle(title string, body string) Article { - return container.CreateArticleUseCase.CreateAarticle(CreateArticleCommand{Title: title, Body: body}) +func postArticle(w http.ResponseWriter, r *http.Request) { + var article Article + err := json.NewDecoder(r.Body).Decode(&article) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + createdArticle := container.CreateArticleUseCase.CreateAarticle(CreateArticleCommand{ + Title: article.Title, + Body: article.Body, + }) + articleJson, _ := json.Marshal(createdArticle) + + _, _ = w.Write(articleJson) +} + +func listArticles(w http.ResponseWriter, _ *http.Request) { + articles := container.ListArticlesUseCase.ListArticles() + articlesJson, _ := json.Marshal(articles) + + _, _ = w.Write(articlesJson) +} + +func NewArticleRouter() http.Handler { + r := chi.NewRouter() + r.Get("/{id}", getArticle) + r.Post("/", postArticle) + r.Get("/", listArticles) + return r } diff --git a/api/dependecyInjection.go b/api/dependecyInjection.go index b9bd98a..b6ea891 100644 --- a/api/dependecyInjection.go +++ b/api/dependecyInjection.go @@ -2,40 +2,40 @@ package api import ( . "GohCMS2/useCases" - "errors" "go.uber.org/dig" ) type Container struct { CreateArticleUseCase *CreateArticleUseCase GetArticleUseCase *GetArticleUseCase + ListArticlesUseCase *ListArticlesUseCase } var container *Container -func InitContainer() *Container { +func createContainer( + createArticle *CreateArticleUseCase, + getArticle *GetArticleUseCase, + listArticle *ListArticlesUseCase, +) *Container { + container = &Container{ + CreateArticleUseCase: createArticle, + GetArticleUseCase: getArticle, + ListArticlesUseCase: listArticle, + } + return container +} + +func InitContainer() { if container != nil { - return container + return } digContainer := dig.New() - err1 := digContainer.Provide(NewCreateArticleUseCase) - err2 := digContainer.Provide(NewGetArticleUseCase) + _ = digContainer.Provide(NewCreateArticleUseCase) + _ = digContainer.Provide(NewGetArticleUseCase) + _ = digContainer.Provide(NewListArticlesUseCase) - if err := errors.Join(err1, err2); err != nil { - panic(err) - } - - err := digContainer.Invoke(func(createArticle *CreateArticleUseCase, getArticle *GetArticleUseCase) { - container = &Container{ - CreateArticleUseCase: createArticle, - GetArticleUseCase: getArticle, - } - }) - if err != nil { - panic(err) - } - - return container + _ = digContainer.Invoke(createContainer) } diff --git a/cmd/main.go b/cmd/main.go index 46f0c5e..935ce51 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,12 +2,30 @@ package main import ( "GohCMS2/api" + "encoding/json" "fmt" + "github.com/go-chi/chi/v5" + "github.com/go-chi/httplog" + "net/http" ) func main() { api.InitContainer() - fmt.Println(api.CreateArticle("Title", "Content")) - fmt.Println(api.GetArticle(1)) + r := chi.NewRouter() + r.Get("/", func(w http.ResponseWriter, r *http.Request) { + msg, _ := json.Marshal(map[string]string{"message": "Hello World"}) + _, _ = w.Write(msg) + }) + r.Mount("/article", api.NewArticleRouter()) + + apiRouter := chi.NewRouter() + apiRouter.Use(httplog.RequestLogger(httplog.NewLogger("GohCMS2"))) + apiRouter.Mount("/v1", r) + + fmt.Println("Server starting on port 8080") + err := http.ListenAndServe(":8080", apiRouter) + if err != nil { + panic(err) + } } diff --git a/domain/article/article.go b/domain/article/article.go index cf3623c..b932822 100644 --- a/domain/article/article.go +++ b/domain/article/article.go @@ -1,11 +1,11 @@ package article type Article struct { - Id int - Title string - Body string - createdAt string - updatedAt string + Id int `json:"id"` + Title string `json:"title"` + Body string `json:"body"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` } func FromApi( @@ -29,7 +29,7 @@ func FromDb( Id: id, Title: title, Body: body, - createdAt: createdAt, - updatedAt: updatedAt, + CreatedAt: createdAt, + UpdatedAt: updatedAt, } } diff --git a/domain/gateways/IArticleRepository.go b/domain/gateways/IArticleRepository.go index b34f888..4f8b504 100644 --- a/domain/gateways/IArticleRepository.go +++ b/domain/gateways/IArticleRepository.go @@ -6,5 +6,6 @@ import ( type IArticleRepository interface { Get(id int) Article + GetAll() []Article Create(article Article) Article } diff --git a/go.mod b/go.mod index a4b9079..18880af 100644 --- a/go.mod +++ b/go.mod @@ -11,4 +11,15 @@ require ( golang.org/x/text v0.10.0 ) -require go.uber.org/dig v1.17.0 +require ( + github.com/go-chi/httplog v0.3.1 + go.uber.org/dig v1.17.0 +) + +require ( + github.com/go-chi/chi/v5 v5.0.10 + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/rs/zerolog v1.29.1 // indirect + golang.org/x/sys v0.10.0 // indirect +) diff --git a/go.sum b/go.sum index 1007972..32f4b84 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,30 @@ +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= +github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/httplog v0.3.1 h1:uC3IUWCZagtbCinb3ypFh36SEcgd6StWw2Bu0XSXRtg= +github.com/go-chi/httplog v0.3.1/go.mod h1:UoiQQ/MTZH5V6JbNB2FzF0DynTh5okpXxlhsyxoP5m8= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 h1:ECW73yc9MY7935nNYXUkK7Dz17YuSUI9yqRqYS8aBww= github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= +github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/steebchen/prisma-client-go v0.21.0 h1:mWBW4eDbKKdLJ8ET2kj0U8myDIVEPuZFRT7En7Yf7YU= @@ -37,9 +55,15 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= diff --git a/useCases/ListArticlesUseCase.go b/useCases/ListArticlesUseCase.go new file mode 100644 index 0000000..b1d1fd4 --- /dev/null +++ b/useCases/ListArticlesUseCase.go @@ -0,0 +1,20 @@ +package useCases + +import ( + . "GohCMS2/adapters/secondary/gateways" + . "GohCMS2/domain/article" +) + +type ListArticlesUseCase struct { + articleRepository ArticleRepository +} + +func NewListArticlesUseCase() *ListArticlesUseCase { + return &ListArticlesUseCase{ + articleRepository: *NewArticleRepository(), + } +} + +func (g *ListArticlesUseCase) ListArticles() []Article { + return g.articleRepository.GetAll() +}