initial commit

This commit is contained in:
maotovisk 2025-08-06 16:04:04 -03:00
parent 9baa0fab25
commit fc46164556
14 changed files with 243 additions and 0 deletions

20
cmd/maot-shortner/main.go Normal file
View file

@ -0,0 +1,20 @@
package main
import (
"fmt"
"maot-shortner/internal/database"
)
func main() {
fmt.Println("Starting app...")
db, err := database.InitDatabase()
if err != nil {
panic(err)
}
server := NewServer(db)
fmt.Println("App listening on port 3032")
server.ListenAndServe()
}

View file

@ -0,0 +1,32 @@
package main
import (
"maot-shortner/internal/database"
"maot-shortner/internal/handlers"
"net/http"
)
type Server struct {
http.Server
db *database.Database
}
func NewServer(db *database.Database) *Server {
return &Server{
Server: http.Server{
Addr: ":3032",
Handler: createMux(db),
},
db: db,
}
}
func createMux(db *database.Database) http.Handler {
r := http.NewServeMux()
linkHandler := handlers.NewLinkHandler(db)
r.HandleFunc("GET /api/links", linkHandler.ListLinks)
r.HandleFunc("GET /{id}", linkHandler.GetUrl)
return r
}

12
go.mod Normal file
View file

@ -0,0 +1,12 @@
module maot-shortner
go 1.24.5
require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/mattn/go-sqlite3 v1.14.30 // indirect
golang.org/x/text v0.27.0 // indirect
gorm.io/driver/sqlite v1.6.0 // indirect
gorm.io/gorm v1.30.1 // indirect
)

12
go.sum Normal file
View file

@ -0,0 +1,12 @@
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/mattn/go-sqlite3 v1.14.30 h1:bVreufq3EAIG1Quvws73du3/QgdeZ3myglJlrzSYYCY=
github.com/mattn/go-sqlite3 v1.14.30/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
gorm.io/gorm v1.30.1 h1:lSHg33jJTBxs2mgJRfRZeLDG+WZaHYCk3Wtfl6Ngzo4=
gorm.io/gorm v1.30.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=

19
internal/app/routes.go Normal file
View file

@ -0,0 +1,19 @@
package app
import (
"maot-shortner/internal/handlers"
"net/http"
)
type HandlerList struct {
*handlers.LinkHandler
}
func CreateMux(handlers HandlerList) *http.ServeMux {
r := http.NewServeMux()
r.HandleFunc("/links", handlers.LinkHandler.ListLinks)
r.HandleFunc("/", handlers.LinkHandler.Handle)
return r
}

View file

@ -0,0 +1 @@
package config

View file

@ -0,0 +1,23 @@
package database
import (
"log"
"maot-shortner/internal/domain"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type Database struct {
*gorm.DB
}
func InitDatabase() (database *Database, err error) {
log.Println("Starting database...")
db, err := gorm.Open(sqlite.Open("shortener.db"), &gorm.Config{})
db.AutoMigrate(domain.ImportModels()...)
database = &Database{db}
return database, err
}

16
internal/database/link.go Normal file
View file

@ -0,0 +1,16 @@
package database
import (
"context"
"maot-shortner/internal/domain"
)
func (db *Database) GetLinks(ctx context.Context) ([]*domain.Link, error) {
links := make([]*domain.Link, 0)
if err := db.WithContext(ctx).Find(&links).Error; err != nil {
return nil, err
}
return links, nil
}

12
internal/domain/link.go Normal file
View file

@ -0,0 +1,12 @@
package domain
import (
"time"
)
type Link struct {
ID int64 `json:"id"`
ShortURL string `json:"short_url"`
LongURL string `json:"long_url"`
CreatedAt time.Time `json:"created_at"`
}

View file

@ -0,0 +1,7 @@
package domain
func ImportModels() []any {
return []any{
&Link{},
}
}

View file

@ -0,0 +1,7 @@
package handlers
import "net/http"
type Handler interface {
Handle(w http.ResponseWriter, r *http.Request)
}

51
internal/handlers/link.go Normal file
View file

@ -0,0 +1,51 @@
package handlers
import (
"encoding/json"
"fmt"
"maot-shortner/internal/database"
"maot-shortner/internal/services"
"net/http"
)
type Response struct {
Message string `json:"message"`
}
type LinkHandler struct {
db *database.Database
linkService *services.LinkService
}
func (h *LinkHandler) Handle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(&Response{Message: "Ola"})
}
func NewLinkHandler(db *database.Database) *LinkHandler {
return &LinkHandler{
db: db,
linkService: services.NewLinkService(db),
}
}
func (h *LinkHandler) ListLinks(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
linkList, err := h.linkService.GetLinks(r.Context())
if err != nil {
http.Error(w, fmt.Sprintf("Failed to list links: %v", err), http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(linkList)
}
func (h *LinkHandler) GetUrl(w http.ResponseWriter, r *http.Request) {
currentCode := r.PathValue("id")
json.NewEncoder(w).Encode(&Response{Message: currentCode})
}

View file

@ -0,0 +1,10 @@
package repositories
import (
"context"
"maot-shortner/internal/domain"
)
type LinkRepository interface {
GetLinks(ctx context.Context) ([]*domain.Link, error)
}

21
internal/services/link.go Normal file
View file

@ -0,0 +1,21 @@
package services
import (
"context"
"maot-shortner/internal/domain"
"maot-shortner/internal/repositories"
)
type LinkService struct {
repo repositories.LinkRepository
}
func NewLinkService(repo repositories.LinkRepository) *LinkService {
return &LinkService{
repo: repo,
}
}
func (s *LinkService) GetLinks(ctx context.Context) ([]*domain.Link, error) {
return s.repo.GetLinks(ctx)
}