Copy over environment.go and generate .env file in starter
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
.env
|
||||
.idea/
|
||||
tmp/
|
||||
@@ -1,80 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"ersteller-lib/starter/env"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// findRepoRoot walks up from the current working directory until it finds a go.mod file.
|
||||
// It returns the directory containing go.mod, or an error if not found.
|
||||
func findRepoRoot() (string, error) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
curr := wd
|
||||
for {
|
||||
if _, err := os.Stat(filepath.Join(curr, "go.mod")); err == nil {
|
||||
return curr, nil
|
||||
}
|
||||
parent := filepath.Dir(curr)
|
||||
if parent == curr {
|
||||
break
|
||||
}
|
||||
curr = parent
|
||||
}
|
||||
return "", errors.New("could not locate repository root (go.mod not found in any parent directory)")
|
||||
}
|
||||
|
||||
func main() {
|
||||
root, err := findRepoRoot()
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
envPath := filepath.Join(root, ".env")
|
||||
if _, err := os.Stat(envPath); err == nil {
|
||||
fmt.Println(".env already exists at:", envPath)
|
||||
fmt.Println("No changes made. Delete or move the existing .env to regenerate.")
|
||||
return
|
||||
}
|
||||
|
||||
// Build .env content dynamically from keys exposed by env package
|
||||
// so we don't duplicate the list here.
|
||||
keys := env.EnvKeys()
|
||||
|
||||
builder := &strings.Builder{}
|
||||
fmt.Fprintln(builder, "# Environment configuration for Salezenify")
|
||||
fmt.Fprintln(builder, "# Generated by cli/generate_env.go")
|
||||
fmt.Fprintln(builder, "# Fill in the appropriate values for your environment.")
|
||||
fmt.Fprintln(builder)
|
||||
|
||||
// Optional defaults can be set here; leave blank for most keys to avoid assumptions.
|
||||
defaults := map[string]string{
|
||||
"REPOSITORY_TYPE": "postgres",
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
v := defaults[k]
|
||||
if v == "" {
|
||||
fmt.Fprintf(builder, "%s=\n", k)
|
||||
} else {
|
||||
fmt.Fprintf(builder, "%s=%s\n", k, v)
|
||||
}
|
||||
}
|
||||
|
||||
content := builder.String()
|
||||
|
||||
if err := os.WriteFile(envPath, []byte(content), 0600); err != nil {
|
||||
fmt.Println("Failed to write .env:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println(".env file created at:", envPath)
|
||||
fmt.Println("Review and update the values as needed.")
|
||||
}
|
||||
+28
-11
@@ -2,6 +2,8 @@ package create
|
||||
|
||||
import (
|
||||
. "ersteller-lib"
|
||||
"ersteller-lib/starter/env"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -22,6 +24,7 @@ type Params struct {
|
||||
ProjectDir string
|
||||
ModuleName string
|
||||
GoPath string
|
||||
OverwriteEnv bool
|
||||
}
|
||||
|
||||
type StarterCreator struct {
|
||||
@@ -71,6 +74,7 @@ func (s StarterCreator) Create() {
|
||||
|
||||
// Write to <ProjectDir>/main.go
|
||||
targetPath := filepath.Join(s.params.ProjectDir, "main.go")
|
||||
content = s.replaceImports(content)
|
||||
must(os.WriteFile(targetPath, content, 0o644))
|
||||
log.Printf("StarterCreator.Create: wrote starter main.go to %s", targetPath)
|
||||
|
||||
@@ -91,6 +95,24 @@ func (s StarterCreator) Create() {
|
||||
if s.params.DbType == DataBaseTypeSqlite {
|
||||
s.executeDbPush()
|
||||
}
|
||||
|
||||
s.copyFile("../.gitignore", ".gitignore")
|
||||
|
||||
s.createEnvironment()
|
||||
}
|
||||
|
||||
func (s StarterCreator) createEnvironment() {
|
||||
if err := os.MkdirAll(s.params.ProjectDir+"/env", 0o755); err != nil {
|
||||
log.Printf("StarterCreator.Create: failed to create env target directory%v", err)
|
||||
return
|
||||
}
|
||||
//s.copyFile("../env/environment.go", "env/environment.go")
|
||||
content, err := os.ReadFile(filepath.Join(s.thisDir, "../env/environment.go"))
|
||||
must(err)
|
||||
must(os.WriteFile(filepath.Join(s.params.ProjectDir, "env/environment.go"), content, 0o644))
|
||||
|
||||
must(env.GenerateEnvFile(s.params.ProjectDir, s.params.OverwriteEnv))
|
||||
|
||||
}
|
||||
|
||||
func (s StarterCreator) executeDbPush() {
|
||||
@@ -119,17 +141,6 @@ func (s StarterCreator) executeDbPush() {
|
||||
func (s StarterCreator) copyFile(src string, dst string) {
|
||||
content, err := os.ReadFile(filepath.Join(s.thisDir, src))
|
||||
must(err)
|
||||
|
||||
// If we are copying the Prisma schema and the target DB is sqlite,
|
||||
// replace the datasource block accordingly.
|
||||
if dst == "schema.prisma" && s.params.DbType == DataBaseTypeSqlite {
|
||||
pgBlock := "datasource db {\n provider = \"postgresql\"\n url = env(\"DATABASE_URL\")\n}\n"
|
||||
sqliteBlock := "datasource db {\n provider = \"sqlite\"\n url = \"file:./db/sqlite.db\"\n}\n"
|
||||
contentStr := string(content)
|
||||
contentStr = strings.Replace(contentStr, pgBlock, sqliteBlock, 1)
|
||||
content = []byte(contentStr)
|
||||
}
|
||||
|
||||
must(os.WriteFile(filepath.Join(s.params.ProjectDir, dst), content, 0o644))
|
||||
}
|
||||
|
||||
@@ -187,6 +198,12 @@ func (s StarterCreator) executeGetPrismaClient() {
|
||||
must(cmd.Run())
|
||||
}
|
||||
|
||||
func (s StarterCreator) replaceImports(content []byte) []byte {
|
||||
contentString := string(content)
|
||||
contentString = strings.ReplaceAll(contentString, "\"ersteller-lib/starter/env\"", fmt.Sprint("\"", s.params.ModuleName, "/env\""))
|
||||
return []byte(contentString)
|
||||
}
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
Vendored
+79
@@ -2,7 +2,9 @@ package env
|
||||
|
||||
import (
|
||||
. "ersteller-lib"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
@@ -100,3 +102,80 @@ func EnvKeys() []string {
|
||||
EnvKeyKeycloakClientSecret,
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateEnvFile creates a .env file template with all required environment variables
|
||||
// from the EnvKeys function. The file will contain comments and default values where appropriate.
|
||||
func GenerateEnvFile(rootPath string, overwrite bool) error {
|
||||
envPath := filepath.Join(rootPath, ".env")
|
||||
Debug("envPath:", envPath)
|
||||
if !overwrite {
|
||||
if _, err := os.Stat(envPath); err == nil {
|
||||
fmt.Println(".env already exists at:", envPath)
|
||||
fmt.Println("No changes made. Delete or move the existing .env to regenerate.")
|
||||
return fmt.Errorf(".env already exists at: %s", envPath)
|
||||
}
|
||||
}
|
||||
file, err := os.Create(envPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create .env file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Write header comment
|
||||
_, err = file.WriteString("# Environment Variables Configuration\n")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write to .env file: %w", err)
|
||||
}
|
||||
_, err = file.WriteString("# Generated from EnvKeys function\n\n")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write to .env file: %w", err)
|
||||
}
|
||||
|
||||
// Get all environment keys
|
||||
keys := EnvKeys()
|
||||
|
||||
// Define default values and comments for specific keys
|
||||
defaults := map[string]string{
|
||||
EnvKeyRepositoryType: "postgres",
|
||||
EnvKeyIsLocal: "false",
|
||||
EnvKeyIsDev: "false",
|
||||
}
|
||||
|
||||
comments := map[string]string{
|
||||
EnvKeyRepositoryType: "# Repository type (postgres, sqlite, etc.)",
|
||||
EnvKeyDatabaseURL: "# Database connection URL",
|
||||
EnvKeySessionSecret: "# Secret key for session management",
|
||||
EnvKeyBaseURL: "# Base URL of the application",
|
||||
EnvKeyIsLocal: "# Set to true for local development",
|
||||
EnvKeyIsDev: "# Set to true for development mode",
|
||||
EnvKeyGoogleClientID: "# Google OAuth client ID",
|
||||
EnvKeyGoogleClientSecret: "# Google OAuth client secret",
|
||||
EnvKeyGoogleRedirectURL: "# Google OAuth redirect URL",
|
||||
EnvKeyKeycloakDiscoveryURL: "# Keycloak discovery URL",
|
||||
EnvKeyKeycloakClientID: "# Keycloak client ID",
|
||||
EnvKeyKeycloakClientSecret: "# Keycloak client secret",
|
||||
}
|
||||
|
||||
// Write each environment variable
|
||||
for _, key := range keys {
|
||||
// Write comment if available
|
||||
if comment, exists := comments[key]; exists {
|
||||
_, err = file.WriteString(comment + "\n")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write to .env file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Write the environment variable with default value if available
|
||||
if defaultValue, exists := defaults[key]; exists {
|
||||
_, err = file.WriteString(fmt.Sprintf("%s=%s\n", key, defaultValue))
|
||||
} else {
|
||||
_, err = file.WriteString(fmt.Sprintf("%s=\n", key))
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write to .env file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+4
-4
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
. "ersteller-lib"
|
||||
"ersteller-lib/starter/env"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
@@ -10,10 +11,9 @@ func main() {
|
||||
GlobalI18n = GlobalI18nImplementation{}
|
||||
server := NewHtmxServer()
|
||||
|
||||
// Path to the SQLite database
|
||||
dbPath := "db/sqlite.db"
|
||||
// Create database connection
|
||||
db, err := CreateSQLiteConnpool(dbPath)
|
||||
environment := env.LoadEnvironment()
|
||||
|
||||
db, err := CreatePostgresConnpool(environment.DatabaseUrl)
|
||||
if err != nil {
|
||||
Error("Failed to create database connection:", err)
|
||||
panic(err)
|
||||
|
||||
Reference in New Issue
Block a user