feat: basic config, logger, main loop

This commit is contained in:
2025-06-10 17:50:14 +03:00
parent e920caf646
commit ddd3e40575
6 changed files with 159 additions and 135 deletions

141
backend/.gitignore vendored
View File

@@ -1,5 +1,8 @@
# Created by https://www.toptal.com/developers/gitignore/api/go,goland,visualstudiocode,vim # Created by https://www.toptal.com/developers/gitignore/api/vim,dotenv,go
# Edit at https://www.toptal.com/developers/gitignore?templates=go,goland,visualstudiocode,vim # Edit at https://www.toptal.com/developers/gitignore?templates=vim,dotenv,go
### dotenv ###
.env
### Go ### ### Go ###
# If you prefer the allow list template instead of the deny list, see community template: # If you prefer the allow list template instead of the deny list, see community template:
@@ -24,119 +27,6 @@
# Go workspace file # Go workspace file
go.work go.work
### GoLand ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### GoLand Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
# https://plugins.jetbrains.com/plugin/7973-sonarlint
.idea/**/sonarlint/
# SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator-enh.xml
.idea/**/markdown-navigator/
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
.idea/$CACHE_FILE$
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
.idea/codestream.xml
# Azure Toolkit for IntelliJ plugin
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
.idea/**/azureSettings.xml
### Vim ### ### Vim ###
# Swap # Swap
[._]*.s[a-v][a-z] [._]*.s[a-v][a-z]
@@ -158,24 +48,5 @@ tags
# Persistent undo # Persistent undo
[._]*.un~ [._]*.un~
### VisualStudioCode ### # End of https://www.toptal.com/developers/gitignore/api/vim,dotenv,go
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
# End of https://www.toptal.com/developers/gitignore/api/go,goland,visualstudiocode,vim

30
backend/cmd/main.go Normal file
View File

@@ -0,0 +1,30 @@
package main
import (
"github.com/gin-gonic/gin"
"easywish/config"
"easywish/internal/logger"
)
func main() {
// Load the configuration
if err := config.LoadConfig(); err != nil {
panic(err)
}
// Setup logger
logger.InitLogger()
defer logger.GetLogger().Sync()
// Connect & migrate database
// models.Init()
// Setup routes
r := gin.Default()
// serviceController.SetupRoutes(r)
// animalController.SetupRoutes(r)
r.Run()
}

92
backend/config/config.go Normal file
View File

@@ -0,0 +1,92 @@
package config
import (
"log"
"reflect"
"fmt"
"github.com/spf13/viper"
)
type Config struct {
Hostname string `mapstructure:"HOSTNAME"`
Port string `mapstructure:"PORT"`
DatabaseUrl string `mapstructure:"DATABASE_URL"`
RedisUrl string `mapstructure:"REDIS_URL"`
MinioUrl string `mapstructure:"MINIO_URL"`
JwtAlgorithm string `mapstructure:"JWT_ALGORITHM"`
JwtSecret string `mapstructure:"JWT_SECRET"`
JwtIssuer string `mapstructure:"JWT_ISSUER"`
JwtAudience string `mapstructure:"JWT_AUDIENCE"`
JwtExpAccess string `mapstructure:"JWT_EXP_ACCESS"`
JwtExpRefresh string `mapstructure:"JWT_EXP_REFRESH"`
Environment string `mapstructure:"ENVIRONMENT"`
}
var config *Config
// TODO: migrate logging to Zap
func LoadConfig() error {
// Load .env file
if err := viper.ReadInConfig(); err != nil {
log.Printf("Error reading config file, proceeding with environment variables. %s", err)
}
// Set default parameters
viper.SetDefault("HOSTNAME", "localhost")
viper.SetDefault("PORT", "8080")
viper.SetDefault("DATABASE_URL", "mydb")
viper.SetDefault("REDIS_URL", "myredis")
viper.SetDefault("MINIO_URL", "myminio")
viper.SetDefault("JWT_ALGORITHM", "HS256")
viper.SetDefault("JWT_SECRET", "default_jwt_secret_please_change") // TODO: remove and randomly generate
viper.SetDefault("JWT_EXP_ACCESS", "5m")
viper.SetDefault("JWT_EXP_REFRESH", "1w")
viper.SetDefault("JWT_AUDIENCE", "easywish")
viper.SetDefault("JWT_ISSUER", "easywish")
viper.SetDefault("ENVIRONMENT", "production")
// Set the file name and type for Viper
viper.SetConfigName(".env") // name of config file (without extension)
viper.SetConfigType("env") // REQUIRED if the config file does not have the extension
viper.AddConfigPath(".") // optionally look for config in the working directory
// Unmarshal the configuration into the Config struct
if err := viper.Unmarshal(&config); err != nil {
log.Fatalf("Unable to decode into struct, %v", err)
}
// Perform validation
if err := validateConfig(); err != nil {
return err
}
return nil
}
func validateConfig() error {
v := reflect.ValueOf(*config)
t := v.Type()
for i := range v.NumField() {
field := v.Field(i)
fieldType := t.Field(i)
// Check if the field is a string and is empty
if field.Kind() == reflect.String && field.String() == "" {
return fmt.Errorf("Missing required configuration: %s", fieldType.Name)
}
}
return nil
}
func GetConfig() *Config {
return config
}

View File

@@ -29,6 +29,7 @@ require (
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-json v0.10.5 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect

View File

@@ -55,6 +55,8 @@ github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeD
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=

View File

@@ -0,0 +1,28 @@
package logger
import (
"go.uber.org/zap"
"easywish/config"
)
var logger *zap.Logger
func InitLogger() {
var err error
cfg := config.GetConfig()
// TODO: make this configurable
if cfg.Environment == "production" {
logger, err = zap.NewProduction()
} else {
logger, err = zap.NewDevelopment()
}
if err != nil {
panic(err)
}
}
func GetLogger() *zap.Logger {
return logger
}