first commit
All checks were successful
CI / backend (push) Successful in 13m19s
CI / frontend (push) Successful in 11m3s
CI / docker (push) Successful in 1m58s

This commit is contained in:
Cauê Faleiros
2026-06-03 16:31:42 -03:00
commit 8c7e5fbbe4
92 changed files with 18226 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
package config
import (
"log/slog"
"os"
"strconv"
"strings"
"time"
)
type Config struct {
AppEnv string
AppPublicURL string
AppTimezone string
HTTPAddr string
LogLevel slog.Level
DatabaseURL string
SuperAdminEmail string
SuperAdminPassword string
JWTSecret string
AccessTokenTTL time.Duration
RefreshTokenTTL time.Duration
CORSAllowedOrigins []string
CalendarProvider string
CalendarAPIBaseURL string
CalendarAPIKey string
CalendarCacheTTL time.Duration
UploadMaxSizeMB int
UploadAllowedMIMEs []string
StorageDriver string
StorageLocalPath string
SMTPHost string
SMTPPort string
SMTPUser string
SMTPPassword string
SMTPFromEmail string
SMTPFromName string
}
func Load() Config {
return Config{
AppEnv: env("APP_ENV", "development"),
AppPublicURL: env("APP_PUBLIC_URL", "http://localhost:5173"),
AppTimezone: env("APP_TIMEZONE", "America/Sao_Paulo"),
HTTPAddr: env("HTTP_ADDR", ":8080"),
LogLevel: logLevel(env("LOG_LEVEL", "info")),
DatabaseURL: env("DATABASE_URL", "postgres://mira:mira@localhost:5432/mira?sslmode=disable"),
SuperAdminEmail: env("SUPER_ADMIN_EMAIL", ""),
SuperAdminPassword: env("SUPER_ADMIN_PASSWORD", ""),
JWTSecret: env("JWT_SECRET", ""),
AccessTokenTTL: minutes("JWT_ACCESS_TOKEN_TTL_MINUTES", 15),
RefreshTokenTTL: hours("JWT_REFRESH_TOKEN_TTL_DAYS", 7*24),
CORSAllowedOrigins: list("CORS_ALLOWED_ORIGINS", "http://localhost:5173"),
CalendarProvider: env("CALENDAR_PROVIDER", "brasilapi"),
CalendarAPIBaseURL: env("CALENDAR_API_BASE_URL", "https://brasilapi.com.br"),
CalendarAPIKey: env("CALENDAR_API_KEY", ""),
CalendarCacheTTL: hours("CALENDAR_CACHE_TTL_HOURS", 24),
UploadMaxSizeMB: integer("UPLOAD_MAX_SIZE_MB", 10),
UploadAllowedMIMEs: list("UPLOAD_ALLOWED_MIME_TYPES", "image/jpeg,image/png,image/webp,application/pdf"),
StorageDriver: env("STORAGE_DRIVER", "local"),
StorageLocalPath: env("STORAGE_LOCAL_PATH", "/var/lib/mira/uploads"),
SMTPHost: env("SMTP_HOST", ""),
SMTPPort: env("SMTP_PORT", "587"),
SMTPUser: env("SMTP_USER", ""),
SMTPPassword: env("SMTP_PASSWORD", ""),
SMTPFromEmail: env("SMTP_FROM_EMAIL", ""),
SMTPFromName: env("SMTP_FROM_NAME", "Mira"),
}
}
func env(key, fallback string) string {
value := strings.TrimSpace(os.Getenv(key))
if value == "" {
return fallback
}
return value
}
func list(key, fallback string) []string {
raw := env(key, fallback)
parts := strings.Split(raw, ",")
values := make([]string, 0, len(parts))
for _, part := range parts {
value := strings.TrimSpace(part)
if value != "" {
values = append(values, value)
}
}
return values
}
func integer(key string, fallback int) int {
value, err := strconv.Atoi(env(key, ""))
if err != nil {
return fallback
}
return value
}
func minutes(key string, fallback int) time.Duration {
return time.Duration(integer(key, fallback)) * time.Minute
}
func hours(key string, fallback int) time.Duration {
return time.Duration(integer(key, fallback)) * time.Hour
}
func logLevel(value string) slog.Level {
switch strings.ToLower(value) {
case "debug":
return slog.LevelDebug
case "warn":
return slog.LevelWarn
case "error":
return slog.LevelError
default:
return slog.LevelInfo
}
}