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.")
|
|
||||||
}
|
|
||||||
+32
-15
@@ -2,6 +2,8 @@ package create
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
. "ersteller-lib"
|
. "ersteller-lib"
|
||||||
|
"ersteller-lib/starter/env"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -18,10 +20,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Params struct {
|
type Params struct {
|
||||||
DbType DatabaseType
|
DbType DatabaseType
|
||||||
ProjectDir string
|
ProjectDir string
|
||||||
ModuleName string
|
ModuleName string
|
||||||
GoPath string
|
GoPath string
|
||||||
|
OverwriteEnv bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type StarterCreator struct {
|
type StarterCreator struct {
|
||||||
@@ -71,6 +74,7 @@ func (s StarterCreator) Create() {
|
|||||||
|
|
||||||
// Write to <ProjectDir>/main.go
|
// Write to <ProjectDir>/main.go
|
||||||
targetPath := filepath.Join(s.params.ProjectDir, "main.go")
|
targetPath := filepath.Join(s.params.ProjectDir, "main.go")
|
||||||
|
content = s.replaceImports(content)
|
||||||
must(os.WriteFile(targetPath, content, 0o644))
|
must(os.WriteFile(targetPath, content, 0o644))
|
||||||
log.Printf("StarterCreator.Create: wrote starter main.go to %s", targetPath)
|
log.Printf("StarterCreator.Create: wrote starter main.go to %s", targetPath)
|
||||||
|
|
||||||
@@ -91,6 +95,24 @@ func (s StarterCreator) Create() {
|
|||||||
if s.params.DbType == DataBaseTypeSqlite {
|
if s.params.DbType == DataBaseTypeSqlite {
|
||||||
s.executeDbPush()
|
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() {
|
func (s StarterCreator) executeDbPush() {
|
||||||
@@ -119,17 +141,6 @@ func (s StarterCreator) executeDbPush() {
|
|||||||
func (s StarterCreator) copyFile(src string, dst string) {
|
func (s StarterCreator) copyFile(src string, dst string) {
|
||||||
content, err := os.ReadFile(filepath.Join(s.thisDir, src))
|
content, err := os.ReadFile(filepath.Join(s.thisDir, src))
|
||||||
must(err)
|
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))
|
must(os.WriteFile(filepath.Join(s.params.ProjectDir, dst), content, 0o644))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +198,12 @@ func (s StarterCreator) executeGetPrismaClient() {
|
|||||||
must(cmd.Run())
|
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) {
|
func must(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
Vendored
+79
@@ -2,7 +2,9 @@ package env
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
. "ersteller-lib"
|
. "ersteller-lib"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
@@ -100,3 +102,80 @@ func EnvKeys() []string {
|
|||||||
EnvKeyKeycloakClientSecret,
|
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 (
|
import (
|
||||||
. "ersteller-lib"
|
. "ersteller-lib"
|
||||||
|
"ersteller-lib/starter/env"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
@@ -10,10 +11,9 @@ func main() {
|
|||||||
GlobalI18n = GlobalI18nImplementation{}
|
GlobalI18n = GlobalI18nImplementation{}
|
||||||
server := NewHtmxServer()
|
server := NewHtmxServer()
|
||||||
|
|
||||||
// Path to the SQLite database
|
environment := env.LoadEnvironment()
|
||||||
dbPath := "db/sqlite.db"
|
|
||||||
// Create database connection
|
db, err := CreatePostgresConnpool(environment.DatabaseUrl)
|
||||||
db, err := CreateSQLiteConnpool(dbPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Failed to create database connection:", err)
|
Error("Failed to create database connection:", err)
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
Reference in New Issue
Block a user