feat: basic config, logger, main loop
This commit is contained in:
141
backend/.gitignore
vendored
141
backend/.gitignore
vendored
@@ -1,5 +1,8 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/go,goland,visualstudiocode,vim
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=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=vim,dotenv,go
|
||||
|
||||
### dotenv ###
|
||||
.env
|
||||
|
||||
### Go ###
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
@@ -24,119 +27,6 @@
|
||||
# Go workspace file
|
||||
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 ###
|
||||
# Swap
|
||||
[._]*.s[a-v][a-z]
|
||||
@@ -158,24 +48,5 @@ tags
|
||||
# Persistent undo
|
||||
[._]*.un~
|
||||
|
||||
### VisualStudioCode ###
|
||||
.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
|
||||
# End of https://www.toptal.com/developers/gitignore/api/vim,dotenv,go
|
||||
|
||||
|
||||
30
backend/cmd/main.go
Normal file
30
backend/cmd/main.go
Normal 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
92
backend/config/config.go
Normal 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
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ require (
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // 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/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
|
||||
@@ -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/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/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/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
|
||||
28
backend/internal/logger/logger.go
Normal file
28
backend/internal/logger/logger.go
Normal 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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user