Skip to content

Commit

Permalink
feat(api): upgrade api
Browse files Browse the repository at this point in the history
  • Loading branch information
mezotv committed Oct 4, 2024
1 parent 2b52f04 commit ad1510f
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 88 deletions.
1 change: 1 addition & 0 deletions data/creators/africa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions data/creators/asia.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions data/creators/north-america.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions data/creators/oceania.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions data/creators/south-america.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
82 changes: 0 additions & 82 deletions packages/api/api.go

This file was deleted.

2 changes: 1 addition & 1 deletion packages/api/go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module creatorlink/api
module creatorlink

go 1.23.0
49 changes: 49 additions & 0 deletions packages/api/handlers/creator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package handlers

import (
"encoding/json"
"net/http"
"creatorlink/types"
)

type CreatorHandler struct {
creatorService types.CreatorService
}

func NewCreatorHandler(creatorService types.CreatorService) *CreatorHandler {
return &CreatorHandler{
creatorService: creatorService,
}
}

func (h *CreatorHandler) HandleGetCreator(w http.ResponseWriter, r *http.Request) {
creatorID := r.PathValue("creatorID")
continent := r.PathValue("continent")

creator, err := h.creatorService.GetCreator(continent, creatorID)
if err != nil {
sendErrorResponse(w, err.Error(), http.StatusNotFound)
return
}

sendSuccessResponse(w, creator)
}

func sendSuccessResponse(w http.ResponseWriter, data interface{}) {
response := types.APIResponse{
Status: "success",
Data: data,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}

func sendErrorResponse(w http.ResponseWriter, message string, statusCode int) {
response := types.APIResponse{
Status: "error",
Message: message,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode)
json.NewEncoder(w).Encode(response)
}
8 changes: 3 additions & 5 deletions packages/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import (
)

func main() {
server := NewAPIServer(":6575")
server.Run()
if server != nil {
log.Fatal(server)
}
dataPath := "../../data/creators" // Adjust this path as needed
server := NewAPIServer(":8080", dataPath)
log.Fatal(server.Run())
}
13 changes: 13 additions & 0 deletions packages/api/routes/routes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package routes

import (
"net/http"
"creatorlink/handlers"
"creatorlink/services"
)

func RegisterRoutes(router *http.ServeMux, creatorService *services.CreatorService) {
creatorHandler := handlers.NewCreatorHandler(creatorService)

router.HandleFunc("GET /{continent}/creator/{creatorID}", creatorHandler.HandleGetCreator)
}
41 changes: 41 additions & 0 deletions packages/api/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"log"
"net/http"
"creatorlink/routes"
"creatorlink/services"
)

type APIServer struct {
port string
dataPath string
}

func NewAPIServer(port string, dataPath string) *APIServer {
return &APIServer{
port: port,
dataPath: dataPath,
}
}

func (s *APIServer) Run() error {
router := http.NewServeMux()

// Initialize services
creatorService := services.NewCreatorService(s.dataPath)

// Register routes
routes.RegisterRoutes(router, creatorService)

v1 := http.NewServeMux()
v1.Handle("/api/v1/", http.StripPrefix("/api/v1", router))

server := http.Server{
Addr: s.port,
Handler: v1,
}

log.Printf("Server has started on %s", s.port)
return server.ListenAndServe()
}
115 changes: 115 additions & 0 deletions packages/api/services/creator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package services

import (
"encoding/json"
"fmt"
"io/fs"
"os"
"path/filepath"
"creatorlink/types"
)

type CreatorService struct {
dataPath string
}

func NewCreatorService(dataPath string) *CreatorService {
return &CreatorService{
dataPath: dataPath,
}
}

func (s *CreatorService) GetCreator(continent, creatorID string) (types.Creator, error) {
if continent == "worldwide" {
return s.searchAllContinents(creatorID)
}

return s.searchSingleContinent(continent, creatorID)
}

func (s *CreatorService) searchSingleContinent(continent, creatorID string) (types.Creator, error) {
filePath := filepath.Join(s.dataPath, fmt.Sprintf("%s.json", continent))
creators, err := s.loadCreators(filePath)
if err != nil {
return nil, fmt.Errorf("failed to load creators data for %s: %v", continent, err)
}

creator, found := s.findCreator(creators, creatorID)
if !found {
return nil, fmt.Errorf("creator not found in %s", continent)
}

return creator, nil
}

func (s *CreatorService) searchAllContinents(creatorID string) (types.Creator, error) {
var searchErrors []string

err := filepath.WalkDir(s.dataPath, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}

if d.IsDir() || filepath.Ext(path) != ".json" {
return nil
}

creators, err := s.loadCreators(path)
if err != nil {
searchErrors = append(searchErrors, fmt.Sprintf("error loading %s: %v", path, err))
return nil
}

if creator, found := s.findCreator(creators, creatorID); found {
return &foundCreator{creator: creator}
}

return nil
})

if err != nil {
if ferr, ok := err.(*foundCreator); ok {
return ferr.creator, nil
}
return nil, fmt.Errorf("error searching creators: %v", err)
}

if len(searchErrors) > 0 {
return nil, fmt.Errorf("some errors occurred while searching: %v", searchErrors)
}

return nil, fmt.Errorf("creator not found in any continent")
}

func (s *CreatorService) loadCreators(filePath string) ([]types.Creator, error) {
fileContent, err := os.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("error reading file: %v", err)
}

var creators []types.Creator
err = json.Unmarshal(fileContent, &creators)
if err != nil {
return nil, fmt.Errorf("error unmarshalling JSON: %v", err)
}

return creators, nil
}

func (s *CreatorService) findCreator(creators []types.Creator, creatorID string) (types.Creator, bool) {
for _, creator := range creators {
if _, ok := creator[creatorID]; ok {
return creator, true
}
}
return nil, false
}

// Custom error type to handle found creator
type foundCreator struct {
creator types.Creator
}

func (e *foundCreator) Error() string {
return "creator found"
}
13 changes: 13 additions & 0 deletions packages/api/types/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package types

type Creator map[string]interface{}

type APIResponse struct {
Status string `json:"status"`
Data interface{} `json:"data,omitempty"`
Message string `json:"message,omitempty"`
}

type CreatorService interface {
GetCreator(continent, creatorID string) (Creator, error)
}

0 comments on commit ad1510f

Please sign in to comment.