chore: update port so it doesn't conflict with sso

This commit is contained in:
Hafizh A. Y
2025-09-30 16:48:05 +07:00
parent 94a6d41a61
commit dbc1f79a36
19 changed files with 668 additions and 37 deletions
+4 -2
View File
@@ -3,8 +3,8 @@
VERSION=0.0.1 VERSION=0.0.1
APP_ENV=dev APP_ENV=dev
APP_HOST=0.0.0.0 APP_HOST=0.0.0.0
APP_PORT=8080 APP_PORT=8081
APP_URL=http://localhost:8080 APP_URL=http://localhost:8081
# database configuration # database configuration
DB_HOST=postgresdb DB_HOST=postgresdb
@@ -12,6 +12,7 @@ DB_USER=postgres
DB_PASSWORD=changeme DB_PASSWORD=changeme
DB_NAME=db_lti_erp DB_NAME=db_lti_erp
DB_PORT=5432 DB_PORT=5432
DB_PORT_HOST=5542
# JWT # JWT
JWT_SECRET=changeme JWT_SECRET=changeme
@@ -30,3 +31,4 @@ CORS_MAX_AGE=600
# Redis # Redis
REDIS_URL=redis://redis:6379/0 REDIS_URL=redis://redis:6379/0
REDIS_PORT_HOST=6381
+1 -1
View File
@@ -15,6 +15,6 @@ RUN go mod download
# Copy source code # Copy source code
COPY . . COPY . .
EXPOSE 8080 EXPOSE 8081
CMD ["air", "-c", ".air.toml"] CMD ["air", "-c", ".air.toml"]
+4 -4
View File
@@ -3,7 +3,7 @@ services:
image: postgres:alpine image: postgres:alpine
restart: always restart: always
ports: ports:
- "${DB_PORT:-5432}:5432" - "${DB_PORT_HOST:-5542}:5432"
environment: environment:
POSTGRES_USER: ${DB_USER:-postgres} POSTGRES_USER: ${DB_USER:-postgres}
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres} POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
@@ -25,7 +25,7 @@ services:
image: redis:7-alpine image: redis:7-alpine
restart: unless-stopped restart: unless-stopped
ports: ports:
- "6379:6379" - "${REDIS_PORT_HOST:-6381}:6379"
healthcheck: healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"] test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
interval: 5s interval: 5s
@@ -54,13 +54,13 @@ services:
DB_NAME: ${DB_NAME:-db_lti_erp} DB_NAME: ${DB_NAME:-db_lti_erp}
REDIS_URL: ${REDIS_URL:-redis://redis:6379/0} REDIS_URL: ${REDIS_URL:-redis://redis:6379/0}
ports: ports:
- "${APP_PORT:-8080}:8080" - "${APP_PORT:-8081}:8081"
depends_on: depends_on:
postgresdb: postgresdb:
condition: service_healthy condition: service_healthy
networks: [go-network] networks: [go-network]
healthcheck: healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz || exit 1"] test: ["CMD-SHELL", "wget -qO- http://localhost:8081/healthz || exit 1"]
interval: 10s interval: 10s
timeout: 3s timeout: 3s
retries: 10 retries: 10
@@ -13,9 +13,9 @@ DROP TABLE IF EXISTS warehouses;
DROP TABLE IF EXISTS kandangs; DROP TABLE IF EXISTS kandangs;
DROP TABLE IF EXISTS locations; DROP TABLE IF EXISTS locations;
DROP TABLE IF EXISTS areas; DROP TABLE IF EXISTS areas;
DROP TABLE IF EXISTS uom; DROP TABLE IF EXISTS uoms;
DROP TABLE IF EXISTS suppliers; DROP TABLE IF EXISTS suppliers;
DROP TABLE IF EXISTS fcr; DROP TABLE IF EXISTS fcrs;
DROP TABLE IF EXISTS projects; DROP TABLE IF EXISTS projects;
DROP INDEX IF EXISTS users_id_user_unique; DROP INDEX IF EXISTS users_id_user_unique;
DROP INDEX IF EXISTS users_email_unique; DROP INDEX IF EXISTS users_email_unique;
@@ -36,7 +36,7 @@ CREATE TABLE product_categories (
CREATE UNIQUE INDEX product_categories_code_unique ON product_categories (code) WHERE deleted_at IS NULL; CREATE UNIQUE INDEX product_categories_code_unique ON product_categories (code) WHERE deleted_at IS NULL;
-- UOM -- UOM
CREATE TABLE uom ( CREATE TABLE uoms (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW(),
@@ -51,11 +51,11 @@ CREATE TABLE products (
name VARCHAR NOT NULL, name VARCHAR NOT NULL,
brand VARCHAR NOT NULL, brand VARCHAR NOT NULL,
sku VARCHAR(100), sku VARCHAR(100),
uom_id BIGINT NOT NULL REFERENCES uom(id), uom_id BIGINT NOT NULL REFERENCES uoms(id),
product_category_id BIGINT NOT NULL REFERENCES product_categories(id), product_category_id BIGINT NOT NULL REFERENCES product_categories(id),
product_price NUMERIC(15,2) NOT NULL, product_price NUMERIC(15,3) NOT NULL,
selling_price NUMERIC(15,2), selling_price NUMERIC(15,3),
tax NUMERIC(15,2), tax NUMERIC(15,3),
expiry_period INT, expiry_period INT,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(),
@@ -134,7 +134,7 @@ CREATE TABLE customers (
phone VARCHAR(20) NOT NULL, phone VARCHAR(20) NOT NULL,
email VARCHAR NOT NULL, email VARCHAR NOT NULL,
account_number VARCHAR(50) NOT NULL, account_number VARCHAR(50) NOT NULL,
balance NUMERIC(15,2) DEFAULT 0, balance NUMERIC(15,3) DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
@@ -145,7 +145,7 @@ CREATE TABLE customers (
CREATE TABLE nonstocks ( CREATE TABLE nonstocks (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR NOT NULL,
uom_id BIGINT NOT NULL REFERENCES uom(id), uom_id BIGINT NOT NULL REFERENCES uoms(id),
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ,
@@ -153,7 +153,7 @@ CREATE TABLE nonstocks (
); );
-- FCR -- FCR
CREATE TABLE fcr ( CREATE TABLE fcrs (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW(),
@@ -164,10 +164,10 @@ CREATE TABLE fcr (
CREATE TABLE fcr_standards ( CREATE TABLE fcr_standards (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
fcr_id BIGINT NOT NULL REFERENCES fcr(id) ON DELETE CASCADE ON UPDATE CASCADE, fcr_id BIGINT NOT NULL REFERENCES fcrs(id) ON DELETE CASCADE ON UPDATE CASCADE,
weight NUMERIC(15,2) NOT NULL, weight NUMERIC(15,3) NOT NULL,
fcr_number NUMERIC(15,2) NOT NULL, fcr_number NUMERIC(15,3) NOT NULL,
mortality NUMERIC(15,2) NOT NULL, mortality NUMERIC(15,3) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ deleted_at TIMESTAMPTZ
@@ -186,7 +186,7 @@ CREATE TABLE suppliers (
address TEXT NOT NULL, address TEXT NOT NULL,
npwp VARCHAR(50), npwp VARCHAR(50),
account_number VARCHAR(50), account_number VARCHAR(50),
balance NUMERIC(15,2) DEFAULT 0, balance NUMERIC(15,3) DEFAULT 0,
due_date INT NOT NULL, due_date INT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(),
+13
View File
@@ -0,0 +1,13 @@
package master
import (
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
)
type MasterModule struct{}
func (MasterModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) {
RegisterRoutes(router, db, validate)
}
+25
View File
@@ -0,0 +1,25 @@
package master
import (
"gitlab.com/mbugroup/lti-api.git/internal/modules"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
uoms "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms"
// MODULE IMPORTS
)
func RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) {
group := router.Group("/master")
allModules := []modules.Module{
uoms.UomModule{},
// MODULE REGISTRY
}
for _, m := range allModules {
m.RegisterRoutes(group, db, validate)
}
}
@@ -0,0 +1,140 @@
package controller
import (
"math"
"strconv"
"gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/dto"
service "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/services"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/validations"
"gitlab.com/mbugroup/lti-api.git/internal/response"
"github.com/gofiber/fiber/v2"
)
type UomController struct {
UomService service.UomService
}
func NewUomController(uomService service.UomService) *UomController {
return &UomController{
UomService: uomService,
}
}
func (u *UomController) GetAll(c *fiber.Ctx) error {
query := &validation.Query{
Page: c.QueryInt("page", 1),
Limit: c.QueryInt("limit", 10),
Search: c.Query("search", ""),
}
result, totalResults, err := u.UomService.GetAll(c, query)
if err != nil {
return err
}
return c.Status(fiber.StatusOK).
JSON(response.SuccessWithPaginate[dto.UomListDTO]{
Code: fiber.StatusOK,
Status: "success",
Message: "Get all uoms successfully",
Meta: response.Meta{
Page: query.Page,
Limit: query.Limit,
TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))),
TotalResults: totalResults,
},
Data: dto.ToUomListDTOs(result),
})
}
func (u *UomController) GetOne(c *fiber.Ctx) error {
param := c.Params("id")
id, err := strconv.Atoi(param)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
}
result, err := u.UomService.GetOne(c, uint(id))
if err != nil {
return err
}
return c.Status(fiber.StatusOK).
JSON(response.Success{
Code: fiber.StatusOK,
Status: "success",
Message: "Get uom successfully",
Data: dto.ToUomListDTO(*result),
})
}
func (u *UomController) CreateOne(c *fiber.Ctx) error {
req := new(validation.Create)
if err := c.BodyParser(req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
}
result, err := u.UomService.CreateOne(c, req)
if err != nil {
return err
}
return c.Status(fiber.StatusCreated).
JSON(response.Success{
Code: fiber.StatusCreated,
Status: "success",
Message: "Create uom successfully",
Data: dto.ToUomListDTO(*result),
})
}
func (u *UomController) UpdateOne(c *fiber.Ctx) error {
req := new(validation.Update)
param := c.Params("id")
id, err := strconv.Atoi(param)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
}
if err := c.BodyParser(req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
}
result, err := u.UomService.UpdateOne(c, req, uint(id))
if err != nil {
return err
}
return c.Status(fiber.StatusOK).
JSON(response.Success{
Code: fiber.StatusOK,
Status: "success",
Message: "Update uom successfully",
Data: dto.ToUomListDTO(*result),
})
}
func (u *UomController) DeleteOne(c *fiber.Ctx) error {
param := c.Params("id")
id, err := strconv.Atoi(param)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
}
if err := u.UomService.DeleteOne(c, uint(id)); err != nil {
return err
}
return c.Status(fiber.StatusOK).
JSON(response.Common{
Code: fiber.StatusOK,
Status: "success",
Message: "Delete uom successfully",
})
}
@@ -0,0 +1,49 @@
package dto
import (
"time"
model "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/models"
)
// === DTO Structs ===
type UomBaseDTO struct {
Id uint `json:"id"`
Name string `json:"name"`
}
type UomListDTO struct {
UomBaseDTO
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type UomDetailDTO struct {
UomListDTO
}
// === Mapper Functions ===
func ToUomBaseDTO(m model.Uom) UomBaseDTO {
return UomBaseDTO{
Id: m.Id,
Name: m.Name,
}
}
func ToUomListDTO(m model.Uom) UomListDTO {
return UomListDTO{
UomBaseDTO: ToUomBaseDTO(m),
CreatedAt: m.CreatedAt,
UpdatedAt: m.UpdatedAt,
}
}
func ToUomListDTOs(m []model.Uom) []UomListDTO {
result := make([]UomListDTO, len(m))
for i, r := range m {
result[i] = ToUomListDTO(r)
}
return result
}
@@ -0,0 +1,19 @@
package model
import (
"time"
model "gitlab.com/mbugroup/lti-api.git/internal/modules/users/models"
"gorm.io/gorm"
)
type Uom struct {
Id uint `gorm:"primaryKey"`
Name string `gorm:"not null"`
CreatedBy int64 `gorm:"not null"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
CreatedUser model.User `gorm:"foreignKey:CreatedBy;references:Id"`
}
+26
View File
@@ -0,0 +1,26 @@
package uoms
import (
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
rUom "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/repositories"
sUom "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/services"
rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
sUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
)
type UomModule struct{}
func (UomModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) {
uomRepo := rUom.NewUomRepository(db)
userRepo := rUser.NewUserRepository(db)
uomService := sUom.NewUomService(uomRepo, validate)
userService := sUser.NewUserService(userRepo, validate)
UomRoutes(router, userService, uomService)
}
@@ -0,0 +1,21 @@
package repository
import (
model "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/models"
"gitlab.com/mbugroup/lti-api.git/internal/repository"
"gorm.io/gorm"
)
type UomRepository interface {
repository.BaseRepository[model.Uom]
}
type UomRepositoryImpl struct {
*repository.BaseRepositoryImpl[model.Uom]
}
func NewUomRepository(db *gorm.DB) UomRepository {
return &UomRepositoryImpl{
BaseRepositoryImpl: repository.NewBaseRepository[model.Uom](db),
}
}
+28
View File
@@ -0,0 +1,28 @@
package uoms
import (
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/controllers"
uom "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
"github.com/gofiber/fiber/v2"
)
func UomRoutes(v1 fiber.Router, u user.UserService, s uom.UomService) {
ctrl := controller.NewUomController(s)
route := v1.Group("/uoms")
// route.Get("/", m.Auth(u), ctrl.GetAll)
// route.Post("/", m.Auth(u), ctrl.CreateOne)
// route.Get("/:id", m.Auth(u), ctrl.GetOne)
// route.Patch("/:id", m.Auth(u), ctrl.UpdateOne)
// route.Delete("/:id", m.Auth(u), ctrl.DeleteOne)
route.Get("/", ctrl.GetAll)
route.Post("/", ctrl.CreateOne)
route.Get("/:id", ctrl.GetOne)
route.Patch("/:id", ctrl.UpdateOne)
route.Delete("/:id", ctrl.DeleteOne)
}
@@ -0,0 +1,120 @@
package service
import (
"errors"
model "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/models"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
type UomService interface {
GetAll(ctx *fiber.Ctx, params *validation.Query) ([]model.Uom, int64, error)
GetOne(ctx *fiber.Ctx, id uint) (*model.Uom, error)
CreateOne(ctx *fiber.Ctx, req *validation.Create) (*model.Uom, error)
UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint) (*model.Uom, error)
DeleteOne(ctx *fiber.Ctx, id uint) error
}
type uomService struct {
Log *logrus.Logger
Validate *validator.Validate
Repository repository.UomRepository
}
func NewUomService(repo repository.UomRepository, validate *validator.Validate) UomService {
return &uomService{
Log: utils.Log,
Validate: validate,
Repository: repo,
}
}
func (s uomService) GetAll(c *fiber.Ctx, params *validation.Query) ([]model.Uom, int64, error) {
if err := s.Validate.Struct(params); err != nil {
return nil, 0, err
}
offset := (params.Page - 1) * params.Limit
uoms, total, err := s.Repository.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB {
if params.Search != "" {
return db.Where("name LIKE ?", "%"+params.Search+"%")
}
return db.Order("created_at DESC").Order("updated_at DESC")
})
if err != nil {
s.Log.Errorf("Failed to get uoms: %+v", err)
return nil, 0, err
}
return uoms, total, nil
}
func (s uomService) GetOne(c *fiber.Ctx, id uint) (*model.Uom, error) {
uom, err := s.Repository.GetByID(c.Context(), id, nil)
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "Uom not found")
}
if err != nil {
s.Log.Errorf("Failed get uom by id: %+v", err)
return nil, err
}
return uom, nil
}
func (s *uomService) CreateOne(c *fiber.Ctx, req *validation.Create) (*model.Uom, error) {
if err := s.Validate.Struct(req); err != nil {
return nil, err
}
createBody := &model.Uom{
Name: req.Name,
CreatedBy: 1,
}
if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil {
s.Log.Errorf("Failed to create uom: %+v", err)
return nil, err
}
return createBody, nil
}
func (s uomService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) (*model.Uom, error) {
if err := s.Validate.Struct(req); err != nil {
return nil, err
}
updateBody := make(map[string]any)
if req.Name != nil {
updateBody["name"] = *req.Name
}
if err := s.Repository.PatchOne(c.Context(), id, updateBody, nil); err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "Uom not found")
}
s.Log.Errorf("Failed to update uom: %+v", err)
return nil, err
}
return s.GetOne(c, id)
}
func (s uomService) DeleteOne(c *fiber.Ctx, id uint) error {
if err := s.Repository.DeleteOne(c.Context(), id); err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, "Uom not found")
}
s.Log.Errorf("Failed to delete uom: %+v", err)
return err
}
return nil
}
@@ -0,0 +1,15 @@
package validation
type Create struct {
Name string `json:"name" validate:"required_strict,min=3"`
}
type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty,max=50"`
}
type Query struct {
Page int `query:"page" validate:"omitempty,number,min=1"`
Limit int `query:"limit" validate:"omitempty,number,min=1,max=100"`
Search string `query:"search" validate:"omitempty,max=50"`
}
+2
View File
@@ -7,6 +7,7 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"gorm.io/gorm" "gorm.io/gorm"
master "gitlab.com/mbugroup/lti-api.git/internal/modules/master"
users "gitlab.com/mbugroup/lti-api.git/internal/modules/users" users "gitlab.com/mbugroup/lti-api.git/internal/modules/users"
// MODULE IMPORTS // MODULE IMPORTS
) )
@@ -18,6 +19,7 @@ func Routes(app *fiber.App, db *gorm.DB) {
// root modules di sini // root modules di sini
allModules := []modules.Module{ allModules := []modules.Module{
users.UserModule{}, users.UserModule{},
master.MasterModule{},
// MODULE REGISTRY // MODULE REGISTRY
} }
+166 -5
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"log" "log"
"os" "os"
@@ -15,6 +16,11 @@ type Data struct {
Entity string // last ("area") Entity string // last ("area")
} }
const (
repoBase = "gitlab.com/mbugroup/lti-api.git"
modulesBase = repoBase + "/internal/modules"
)
func main() { func main() {
if len(os.Args) < 2 { if len(os.Args) < 2 {
log.Fatal("usage: make gen feat=<feature> (ex: customer | master/area)") log.Fatal("usage: make gen feat=<feature> (ex: customer | master/area)")
@@ -139,6 +145,7 @@ func main() {
log.Println("Generated:", outFile) log.Println("Generated:", outFile)
} }
updateParentModules(d)
updateMainRoute(d) updateMainRoute(d)
} }
@@ -150,13 +157,22 @@ func updateMainRoute(d Data) {
return return
} }
// entity & path var importPath string
modPath := filepath.Join(append(toCamelParts(d.Parts[:len(d.Parts)-1]), toCamelCase(d.Entity)+"s")...) var modName string
modName := toCamelCase(d.Entity) + "s" var pkgName string
pkgName := toPascalCase(d.Entity) + "Module" if len(d.Parts) > 1 {
top := d.Parts[0]
importPath = toKebab(top)
modName = toCamelCase(top)
pkgName = toPascalCase(top) + "Module"
} else {
importPath = toKebab(d.Entity) + "s"
modName = toCamelCase(d.Entity) + "s"
pkgName = toPascalCase(d.Entity) + "Module"
}
// Inject import // Inject import
importLine := fmt.Sprintf("\t%[1]s \"%s/internal/modules/%s\"", modName, "gitlab.com/mbugroup/lti-api.git", modPath) importLine := fmt.Sprintf("\t%[1]s \"%s/%s\"", modName, modulesBase, importPath)
if !strings.Contains(string(content), importLine) { if !strings.Contains(string(content), importLine) {
content = []byte(strings.Replace(string(content), content = []byte(strings.Replace(string(content),
"// MODULE IMPORTS", "// MODULE IMPORTS",
@@ -179,6 +195,151 @@ func updateMainRoute(d Data) {
log.Println("Updated:", routeFile) log.Println("Updated:", routeFile)
} }
func updateParentModules(d Data) {
if len(d.Parts) < 2 {
return
}
fullLen := len(d.Parts)
for i := 1; i < len(d.Parts); i++ {
parentParts := d.Parts[:i]
ensureParentModuleFile(parentParts)
childParts := d.Parts[:i+1]
ensureParentRoute(parentParts, childParts, fullLen)
}
}
func ensureParentModuleFile(parentParts []string) {
dir := filepath.Join(append([]string{"internal", "modules"}, toKebabParts(parentParts)...)...)
if err := os.MkdirAll(dir, 0o755); err != nil {
log.Fatalf("make parent dir: %v", err)
}
moduleFile := filepath.Join(dir, "module.go")
if _, err := os.Stat(moduleFile); err == nil {
return
} else if !errors.Is(err, os.ErrNotExist) {
log.Fatalf("check parent module: %v", err)
}
pkgName := toPackageName(parentParts[len(parentParts)-1])
structName := toPascalCase(parentParts[len(parentParts)-1]) + "Module"
content := fmt.Sprintf(`package %s
import (
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
)
type %s struct{}
func (%s) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) {
RegisterRoutes(router, db, validate)
}
`, pkgName, structName, structName)
if err := os.WriteFile(moduleFile, []byte(content), 0o644); err != nil {
log.Fatalf("write parent module: %v", err)
}
log.Println("Generated:", moduleFile)
}
func ensureParentRoute(parentParts, childParts []string, fullLen int) {
dir := filepath.Join(append([]string{"internal", "modules"}, toKebabParts(parentParts)...)...)
if err := os.MkdirAll(dir, 0o755); err != nil {
log.Fatalf("make parent dir: %v", err)
}
routeFile := filepath.Join(dir, "route.go")
isLeaf := len(childParts) == fullLen
childName := childParts[len(childParts)-1]
childAlias := toCamelCase(childName)
if isLeaf {
childAlias += "s"
}
childStruct := toPascalCase(childName) + "Module"
childImportParts := toKebabParts(childParts[:len(childParts)-1])
childLast := childParts[len(childParts)-1]
if isLeaf {
childImportParts = append(childImportParts, toKebab(childLast)+"s")
} else {
childImportParts = append(childImportParts, toKebab(childLast))
}
childImportPath := modulesBase + "/" + strings.Join(childImportParts, "/")
if _, err := os.Stat(routeFile); errors.Is(err, os.ErrNotExist) {
pkgName := toPackageName(parentParts[len(parentParts)-1])
segment := toKebab(parentParts[len(parentParts)-1])
content := fmt.Sprintf(`package %s
import (
"%s"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
%s "%s"
// MODULE IMPORTS
)
func RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) {
group := router.Group("/%s")
allModules := []modules.Module{
%s.%s{},
// MODULE REGISTRY
}
for _, m := range allModules {
m.RegisterRoutes(group, db, validate)
}
}
`, pkgName, modulesBase, childAlias, childImportPath, segment, childAlias, childStruct)
if err := os.WriteFile(routeFile, []byte(content), 0o644); err != nil {
log.Fatalf("write parent route: %v", err)
}
log.Println("Generated:", routeFile)
return
} else if err != nil {
log.Fatalf("check parent route: %v", err)
}
content, err := os.ReadFile(routeFile)
if err != nil {
log.Fatalf("read parent route: %v", err)
}
importLine := fmt.Sprintf("\t%s \"%s\"", childAlias, childImportPath)
if !strings.Contains(string(content), importLine) {
content = []byte(strings.Replace(string(content),
"\t// MODULE IMPORTS",
importLine+"\n\t// MODULE IMPORTS",
1))
}
registryLine := fmt.Sprintf("\t\t%s.%s{},", childAlias, childStruct)
if !strings.Contains(string(content), registryLine) {
content = []byte(strings.Replace(string(content),
"\t\t// MODULE REGISTRY",
registryLine+"\n\t\t// MODULE REGISTRY",
1))
}
if err := os.WriteFile(routeFile, content, 0o644); err != nil {
log.Fatalf("write parent route: %v", err)
}
log.Println("Updated:", routeFile)
}
func toPackageName(s string) string {
return strings.ToLower(toPascalCase(s))
}
func toPascalCase(s string) string { func toPascalCase(s string) string {
sep := func(r rune) bool { return r == '_' || r == '-' || r == ' ' || r == '/' } sep := func(r rune) bool { return r == '_' || r == '-' || r == ' ' || r == '/' }
parts := strings.FieldsFunc(s, sep) parts := strings.FieldsFunc(s, sep)
+8 -4
View File
@@ -5,9 +5,13 @@ import (
) )
type {{Pascal .Entity}} struct { type {{Pascal .Entity}} struct {
Id uint `gorm:"primaryKey"` Id uint `gorm:"primaryKey"`
Name string `gorm:"not null"` Name string `gorm:"not null"`
CreatedAt time.Time CreatedBy int64 `gorm:"not null"`
UpdatedAt time.Time CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
CreatedUser model.User `gorm:"foreignKey:CreatedBy;references:Id"`
} }
{{end}} {{end}}
+12 -6
View File
@@ -1,7 +1,7 @@
{{define "route"}}package {{Kebab .Entity}}s {{define "route"}}package {{Kebab .Entity}}s
import ( import (
m "gitlab.com/mbugroup/lti-api.git/internal/middleware" // m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/{{Kebab .FeatName}}s/controllers" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/{{Kebab .FeatName}}s/controllers"
{{Camel .Entity}} "gitlab.com/mbugroup/lti-api.git/internal/modules/{{Kebab .FeatName}}s/services" {{Camel .Entity}} "gitlab.com/mbugroup/lti-api.git/internal/modules/{{Kebab .FeatName}}s/services"
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
@@ -14,10 +14,16 @@ func {{Pascal .Entity}}Routes(v1 fiber.Router, u user.UserService, s {{Camel .En
route := v1.Group("/{{Kebab .Entity}}s") route := v1.Group("/{{Kebab .Entity}}s")
route.Get("/", m.Auth(u), ctrl.GetAll) // route.Get("/", m.Auth(u), ctrl.GetAll)
route.Post("/", m.Auth(u), ctrl.CreateOne) // route.Post("/", m.Auth(u), ctrl.CreateOne)
route.Get("/:id", m.Auth(u), ctrl.GetOne) // route.Get("/:id", m.Auth(u), ctrl.GetOne)
route.Patch("/:id", m.Auth(u), ctrl.UpdateOne) // route.Patch("/:id", m.Auth(u), ctrl.UpdateOne)
route.Delete("/:id", m.Auth(u), ctrl.DeleteOne) // route.Delete("/:id", m.Auth(u), ctrl.DeleteOne)
route.Get("/", ctrl.GetAll)
route.Post("/", ctrl.CreateOne)
route.Get("/:id", ctrl.GetOne)
route.Patch("/:id", ctrl.UpdateOne)
route.Delete("/:id", ctrl.DeleteOne)
} }
{{end}} {{end}}