Initial commit

This commit is contained in:
2025-10-27 14:22:19 +03:00
commit c6e7f13800
23 changed files with 1164 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
package db
import (
"context"
"github.com/jackc/pgx/v5/pgxpool"
"go.uber.org/fx"
)
func NewDBConnection(lc fx.Lifecycle) *pgxpool.Pool {
pool, err := pgxpool.New(context.Background(), "postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable");
if err != nil {
panic(err.Error())
}
if err := pool.Ping(context.Background()); err != nil {
pool.Close()
panic(err.Error())
}
lc.Append(
fx.StopHook(func() {
pool.Close()
}),
)
return pool
}

32
backend/internal/db/db.go Normal file
View File

@@ -0,0 +1,32 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
package db
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
)
type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
return &Queries{
db: tx,
}
}

View File

@@ -0,0 +1,15 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
package db
import (
"github.com/jackc/pgx/v5/pgtype"
)
type FoodItem struct {
Guid pgtype.UUID
Title string
Description string
}

View File

@@ -0,0 +1,28 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: query.sql
package db
import (
"context"
)
const createFoodItem = `-- name: CreateFoodItem :one
INSERT INTO food_items(title, description)
VALUES ($1, $2)
RETURNING guid, title, description
`
type CreateFoodItemParams struct {
Title string
Description string
}
func (q *Queries) CreateFoodItem(ctx context.Context, arg CreateFoodItemParams) (FoodItem, error) {
row := q.db.QueryRow(ctx, createFoodItem, arg.Title, arg.Description)
var i FoodItem
err := row.Scan(&i.Guid, &i.Title, &i.Description)
return i, err
}

View File

@@ -0,0 +1,10 @@
package errs
import "github.com/google/uuid"
type HTTPErrWrapper struct {
HttpCode int
ErrorId uuid.UUID
Description string
Error error
}

View File

@@ -0,0 +1,27 @@
package routes
import (
"net/http"
"sqlc_example/internal/services"
"sqlc_example/models/dto"
"github.com/gin-gonic/gin"
)
func setupFoodRoutes(router *gin.Engine, foodService services.FoodService) {
router.GET("/food", func(ctx *gin.Context) {
var newItemFoodDTO dto.NewFoodItemDTO
if err := ctx.ShouldBindJSON(newItemFoodDTO); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"err": err.Error()})
return
}
guid, serviceErr := foodService.AddFoodItem(newItemFoodDTO); if serviceErr != nil {
ctx.AbortWithStatusJSON(*&serviceErr.HttpCode, gin.H{"error": serviceErr.Error})
return
}
ctx.JSON(http.StatusOK, gin.H{"guid": guid})
})
}

View File

@@ -0,0 +1,49 @@
package routes
import (
"context"
"fmt"
"net/http"
"time"
"github.com/gin-gonic/gin"
"go.uber.org/fx"
)
func NewGinRouter(lc fx.Lifecycle) *gin.Engine {
router := gin.Default()
server := &http.Server{
Addr: fmt.Sprintf(":%s", "8080"),
Handler: router,
}
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
// TODO: log
return
}
}()
return nil
},
OnStop: func(ctx context.Context) error {
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(shutdownCtx); err != nil {
// TODO: log
return nil
}
return nil
},
})
return router
}

View File

@@ -0,0 +1,17 @@
package routes
import (
"sqlc_example/internal/services"
"github.com/gin-gonic/gin"
"go.uber.org/fx"
)
var Module = fx.Module("routes",
fx.Invoke(func (
router *gin.Engine,
foodService services.FoodService,
) {
setupFoodRoutes(router, foodService)
}),
)

View File

@@ -0,0 +1,27 @@
package services
import (
errs "sqlc_example/internal/errors"
"sqlc_example/models/dto"
"github.com/jackc/pgx/v5/pgxpool"
)
type FoodService interface {
AddFoodItem(obj dto.NewFoodItemDTO) (string, *errs.HTTPErrWrapper)
}
type foodServiceImpl struct {
pool *pgxpool.Pool
}
// AddFoodItem implements FoodService.
func (f *foodServiceImpl) AddFoodItem(obj dto.NewFoodItemDTO) (string, *errs.HTTPErrWrapper) {
panic("unimplemented")
}
func NewFoodService(pool *pgxpool.Pool) FoodService {
return &foodServiceImpl{
pool: pool,
}
}

View File

@@ -0,0 +1,9 @@
package services
import "go.uber.org/fx"
var Module = fx.Module("services",
fx.Provide(
NewFoodService,
),
)