]> localhost Git - tq-wave11-pf.git/commitdiff
lesgo
authorJansen <[email protected]>
Thu, 7 Aug 2025 18:33:27 +0000 (14:33 -0400)
committerJansen <[email protected]>
Thu, 7 Aug 2025 18:33:27 +0000 (14:33 -0400)
17 files changed:
Dockerfile [new file with mode: 0644]
cmd/api/main.go [new file with mode: 0644]
compose.yaml [new file with mode: 0644]
go.mod [new file with mode: 0644]
persistence/ingredient.go [new file with mode: 0644]
persistence/inmemory/ingredients.go [new file with mode: 0644]
persistence/inmemory/inmemory.go [new file with mode: 0644]
persistence/persistence.go [new file with mode: 0644]
pkg/core/ingrendient.go [new file with mode: 0644]
pkg/http/dish.go [new file with mode: 0644]
pkg/http/errors.go [new file with mode: 0644]
pkg/http/http.go [new file with mode: 0644]
pkg/http/ingredient.go [new file with mode: 0644]
pkg/http/menu.go [new file with mode: 0644]
pkg/http/middlewares.go [new file with mode: 0644]
pkg/services/errors.go [new file with mode: 0644]
pkg/services/ingredient.go [new file with mode: 0644]

diff --git a/Dockerfile b/Dockerfile
new file mode 100644 (file)
index 0000000..df79eba
--- /dev/null
@@ -0,0 +1,9 @@
+FROM golang:1.24.6
+
+WORKDIR /app
+
+COPY . .
+
+RUN ls
+
+CMD ["go", "run", "cmd/api/main.go"]
diff --git a/cmd/api/main.go b/cmd/api/main.go
new file mode 100644 (file)
index 0000000..0cffd3e
--- /dev/null
@@ -0,0 +1,15 @@
+package main
+
+import (
+       "jsdaj.tq/pf/persistence/inmemory"
+       "jsdaj.tq/pf/pkg/http"
+)
+
+const PORT int = 8080
+
+func main() {
+       persistence := inmemory.NewPersistence()
+
+       serv := http.InitServer(PORT, &persistence)
+       serv.Start()
+}
diff --git a/compose.yaml b/compose.yaml
new file mode 100644 (file)
index 0000000..57c70a8
--- /dev/null
@@ -0,0 +1,9 @@
+services:
+  back:
+    build: .
+    ports:
+      - "8080:8080"
+    develop:
+      watch:
+        - action: rebuild
+          path: .
diff --git a/go.mod b/go.mod
new file mode 100644 (file)
index 0000000..95abab0
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module jsdaj.tq/pf
+
+go 1.24.5
diff --git a/persistence/ingredient.go b/persistence/ingredient.go
new file mode 100644 (file)
index 0000000..8aeca27
--- /dev/null
@@ -0,0 +1,14 @@
+package persistence
+
+import (
+       "jsdaj.tq/pf/pkg/core"
+)
+
+type IngredientRepository interface {
+       IngredientCreate(core.Ingredient) (core.Ingredient, error)
+       IngredientUpdate(core.Ingredient) error
+       IngredientDeactivate(int) error
+       IngredientGet(int) (*core.Ingredient, error)
+       // TODO: add search params
+       IngredientList() ([]core.Ingredient, error)
+}
diff --git a/persistence/inmemory/ingredients.go b/persistence/inmemory/ingredients.go
new file mode 100644 (file)
index 0000000..4a30c48
--- /dev/null
@@ -0,0 +1,39 @@
+package inmemory
+
+import (
+       "errors"
+       "time"
+
+       "jsdaj.tq/pf/pkg/core"
+)
+
+func (p *InmemoryPersistence) IngredientCreate(in core.Ingredient) (core.Ingredient, error) {
+       id := len(p.ingredients) + 1
+
+       createdAt := time.Now()
+
+       in.Id = id
+       in.CreatedAt = &createdAt
+       p.ingredients   = append(p.ingredients, in)
+
+       return in, nil
+}
+
+func (p *InmemoryPersistence) IngredientUpdate(in core.Ingredient) error {
+       return nil
+}
+
+func (p *InmemoryPersistence) IngredientDeactivate(id int) error {
+       return nil
+}
+
+func (p *InmemoryPersistence) IngredientGet(id int) (*core.Ingredient, error) {
+       if id < 0 || id > len(p.ingredients) {
+               return nil, errors.New("not_found")
+       }
+       return &p.ingredients[id-1], nil
+}
+
+func (p *InmemoryPersistence) IngredientList() ([]core.Ingredient, error) {
+       return p.ingredients, nil
+}
diff --git a/persistence/inmemory/inmemory.go b/persistence/inmemory/inmemory.go
new file mode 100644 (file)
index 0000000..b4245fe
--- /dev/null
@@ -0,0 +1,16 @@
+package inmemory
+
+import (
+       "jsdaj.tq/pf/pkg/core"
+)
+
+type InmemoryPersistence struct {
+       ingredients []core.Ingredient
+}
+
+func NewPersistence() InmemoryPersistence {
+       return InmemoryPersistence{
+               ingredients: []core.Ingredient{},
+       }
+}
+
diff --git a/persistence/persistence.go b/persistence/persistence.go
new file mode 100644 (file)
index 0000000..700aac4
--- /dev/null
@@ -0,0 +1,6 @@
+package persistence
+
+type Persistence interface {
+       IngredientRepository
+}
+
diff --git a/pkg/core/ingrendient.go b/pkg/core/ingrendient.go
new file mode 100644 (file)
index 0000000..000cf31
--- /dev/null
@@ -0,0 +1,12 @@
+package core
+
+import "time"
+
+type Ingredient struct {
+       Id          int    `json:"id,omitempty"`
+       Name        string `json:"name"`
+       Quantity    int    `json:"quantity"`
+       Description string `json:"description"`
+       CreatedAt   *time.Time `json:"createdAt,omitempty"`
+}
+
diff --git a/pkg/http/dish.go b/pkg/http/dish.go
new file mode 100644 (file)
index 0000000..b7806e7
--- /dev/null
@@ -0,0 +1,27 @@
+package http
+
+import (
+       shttp "net/http"
+)
+
+func dishHandleCreate(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func dishHandleUpdate(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func dishHandleDelete(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func dishHandleGet(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func dishHandleList(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func dishHandler() shttp.Handler {
+       mux := shttp.NewServeMux()
+
+       mux.HandleFunc("POST /dish", dishHandleCreate)
+       mux.HandleFunc("PUT /dish/{id}", dishHandleUpdate)
+       mux.HandleFunc("DELETE /dish/{id}", dishHandleDelete)
+       mux.HandleFunc("GET /dish/{id}", dishHandleGet)
+       mux.HandleFunc("GET /dish", dishHandleList)
+
+       return mux
+}
diff --git a/pkg/http/errors.go b/pkg/http/errors.go
new file mode 100644 (file)
index 0000000..8806ad2
--- /dev/null
@@ -0,0 +1,42 @@
+package http
+
+import (
+       "encoding/json"
+       shttp "net/http"
+
+       "jsdaj.tq/pf/pkg/services"
+)
+
+type httpError struct {
+       Status int               `json:"status"`
+       Message string `json:"message"`
+}
+
+func handleError(w shttp.ResponseWriter, status int, message string) {
+       response := httpError{
+               Status: status,
+               Message: message,
+       }
+
+       body, err := json.Marshal(response)
+       if err != nil {
+               body = []byte("Something went wrong")
+       }
+
+       w.WriteHeader(status)
+       w.Write(body)
+}
+
+func handleErrorByCode(w shttp.ResponseWriter, status int) {
+       switch status {
+       case shttp.StatusBadRequest:
+               handleError(w, status, "Bad body")
+       default:
+               handleError(w, shttp.StatusInternalServerError, "Something went wrong")
+       }
+}
+
+func handleServiceError(w shttp.ResponseWriter, err services.Error) {
+       status := err.Code.MapToHTTP()
+       handleError(w, status, err.Message)
+}
diff --git a/pkg/http/http.go b/pkg/http/http.go
new file mode 100644 (file)
index 0000000..b614628
--- /dev/null
@@ -0,0 +1,52 @@
+package http
+
+import (
+       "fmt"
+       "log"
+       shttp "net/http"
+
+       "jsdaj.tq/pf/persistence"
+       "jsdaj.tq/pf/pkg/services"
+)
+
+type Server struct {
+       port int
+
+       serv *shttp.Server
+       mux  *shttp.ServeMux
+
+       ingredients services.Ingredient
+}
+
+func (s *Server) Start() {
+       s.initRoutes()
+
+       s.serv.Handler = middlewares(s.mux)
+
+       log.Printf(">> Starting server at :%d\n", s.port)
+       s.serv.ListenAndServe()
+}
+
+func InitServer(port int, persist persistence.Persistence) Server {
+       var mux *shttp.ServeMux = nil
+
+       serv := &shttp.Server{Addr: fmt.Sprintf(":%d", port)}
+
+       ingredientService := services.InitIngredientService(persist)
+
+       return Server{
+               port,
+               serv,
+               mux,
+               ingredientService,
+       }
+}
+
+func (s *Server) initRoutes() {
+       s.mux = shttp.NewServeMux()
+
+       s.mux.Handle("/ingredient", s.ingredientHandler())
+       s.mux.Handle("/dish", dishHandler())
+       s.mux.Handle("/menu", menuHandler())
+}
+
diff --git a/pkg/http/ingredient.go b/pkg/http/ingredient.go
new file mode 100644 (file)
index 0000000..e02cd8f
--- /dev/null
@@ -0,0 +1,68 @@
+package http
+
+import (
+       "encoding/json"
+       "log"
+       shttp "net/http"
+
+       "jsdaj.tq/pf/pkg/core"
+)
+
+func (s *Server) ingredientHandleCreate(w shttp.ResponseWriter, r *shttp.Request) {
+       var input core.Ingredient
+
+       err := json.NewDecoder(r.Body).Decode(&input)
+       if err != nil {
+               log.Printf("!! %s\n", err)
+               handleErrorByCode(w, shttp.StatusBadRequest)
+               return
+       }
+
+       ingredient, err := s.ingredients.Create(input)
+       if err != nil {
+               handleError(w, shttp.StatusInternalServerError, err.Error())
+               return
+       }
+
+       response, err := json.Marshal(ingredient)
+       if err != nil {
+               handleErrorByCode(w, shttp.StatusInternalServerError)
+               return
+       }
+       
+       w.Write(response)
+}
+
+func (s *Server) ingredientHandleUpdate(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func (s *Server) ingredientHandleDelete(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func (s *Server) ingredientHandleGet(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func (s *Server) ingredientHandleList(w shttp.ResponseWriter, r *shttp.Request) {
+       ingredients, err := s.ingredients.List()
+       if err != nil {
+               handleError(w, shttp.StatusInternalServerError, err.Error())
+               return
+       }
+
+       response, err := json.Marshal(ingredients)
+       if err != nil {
+               handleErrorByCode(w, shttp.StatusInternalServerError)
+               return
+       }
+       
+       w.Write(response)
+}
+
+func (s *Server) ingredientHandler() shttp.Handler {
+       mux := shttp.NewServeMux()
+
+       mux.HandleFunc("POST /ingredient", s.ingredientHandleCreate)
+       mux.HandleFunc("PUT /ingredient/{id}", s.ingredientHandleUpdate)
+       mux.HandleFunc("DELETE /ingredient/{id}", s.ingredientHandleDelete)
+       mux.HandleFunc("GET /ingredient/{id}", s.ingredientHandleGet)
+       mux.HandleFunc("GET /ingredient", s.ingredientHandleList)
+
+       return mux
+}
diff --git a/pkg/http/menu.go b/pkg/http/menu.go
new file mode 100644 (file)
index 0000000..01f02cf
--- /dev/null
@@ -0,0 +1,27 @@
+package http
+
+import (
+       shttp "net/http"
+)
+
+func menuHandleCreate(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func menuHandleUpdate(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func menuHandleDelete(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func menuHandleGet(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func menuHandleList(w shttp.ResponseWriter, r *shttp.Request) {}
+
+func menuHandler() shttp.Handler {
+       mux := shttp.NewServeMux()
+
+       mux.HandleFunc("POST /menu", menuHandleCreate)
+       mux.HandleFunc("PUT /menu/{id}", menuHandleUpdate)
+       mux.HandleFunc("DELETE /menu/{id}", menuHandleDelete)
+       mux.HandleFunc("GET /menu/{id}", menuHandleGet)
+       mux.HandleFunc("GET /menu", menuHandleList)
+
+       return mux
+}
diff --git a/pkg/http/middlewares.go b/pkg/http/middlewares.go
new file mode 100644 (file)
index 0000000..c432172
--- /dev/null
@@ -0,0 +1,24 @@
+package http
+
+import (
+       "log"
+       shttp "net/http"
+)
+
+func middlewareLog(next shttp.Handler) shttp.Handler {
+       return shttp.HandlerFunc(func(w shttp.ResponseWriter, r *shttp.Request) {
+               log.Printf("New request :: %s :: %s\n", r.Method, r.URL)
+               next.ServeHTTP(w, r)
+       })
+}
+
+func middlewareJson(next shttp.Handler) shttp.Handler {
+       return shttp.HandlerFunc(func(w shttp.ResponseWriter, r *shttp.Request) {
+               w.Header().Set("content-type", "application/json")
+               next.ServeHTTP(w, r)
+       })
+}
+
+func middlewares(next shttp.Handler) shttp.Handler {
+       return middlewareLog(middlewareJson(next))
+}
diff --git a/pkg/services/errors.go b/pkg/services/errors.go
new file mode 100644 (file)
index 0000000..11f3cb7
--- /dev/null
@@ -0,0 +1,28 @@
+package services
+
+import "fmt"
+
+type ErrorCode int
+
+const (
+       DefaultError   ErrorCode = iota
+       BadInputError 
+)
+
+func (c ErrorCode) MapToHTTP() int {
+       switch c {
+       case BadInputError:
+               return 400
+       default:
+               return 500
+       }
+}
+
+type Error struct {
+       Code ErrorCode
+       Message string
+}
+
+func (e Error) Error() string {
+       return fmt.Sprintf("%d :: %s", e.Code, e.Message)
+}
diff --git a/pkg/services/ingredient.go b/pkg/services/ingredient.go
new file mode 100644 (file)
index 0000000..b3a1bb0
--- /dev/null
@@ -0,0 +1,33 @@
+package services
+
+import (
+       "jsdaj.tq/pf/persistence"
+       "jsdaj.tq/pf/pkg/core"
+)
+
+type Ingredient struct {
+       repository persistence.IngredientRepository
+}
+
+func (s *Ingredient) Create(ingredient core.Ingredient) (*core.Ingredient, error) {
+       ingredient, err := s.repository.IngredientCreate(ingredient)
+       if err != nil {
+               return nil, err
+       }
+       return &ingredient, nil
+}
+
+func (s *Ingredient) List() ([]core.Ingredient, error) {
+       ingredients, err := s.repository.IngredientList()
+       if err != nil {
+               return []core.Ingredient{}, err
+       }
+       return ingredients, nil
+}
+
+func InitIngredientService(repository persistence.IngredientRepository) Ingredient {
+       return Ingredient{
+               repository,
+       }
+}
+