Add starter creator code

This commit is contained in:
Achim Rohn
2025-08-31 23:45:50 +02:00
parent 46c411f9f3
commit f807f47fa5
3 changed files with 152 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
go run github.com/steebchen/prisma-client-go db push --skip-generate
+144
View File
@@ -0,0 +1,144 @@
package create
import (
. "ersteller-lib"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
type DatabaseType string
const (
DatabaseTypePostgres DatabaseType = "postgres"
DataBaseTypeSqlite DatabaseType = "sqlite"
)
type Params struct {
DbType DatabaseType
ProjectDir string
}
type StarterCreator struct {
params Params
thisDir string
}
func NewStarterCreator(params Params) StarterCreator {
// Validate target directory parameter
if params.ProjectDir == "" {
log.Printf("StarterCreator.Create: ProjectDir is empty; nothing to do")
panic("ProjectDir is empty; nothing to do")
}
// Resolve the path to the starter main.go located at ../main.go relative to this file
_, thisFile, _, ok := runtime.Caller(0)
if !ok {
log.Printf("StarterCreator.Create: unable to resolve current file location via runtime.Caller")
panic("unable to resolve current file location via runtime.Caller")
}
thisDir := filepath.Dir(thisFile)
return StarterCreator{
params: params,
thisDir: thisDir,
}
}
// Create reads the starter main.go file bundled with this package
// and writes it into the target project directory as main.go.
// Minimal, side-effecting function with internal error logging to keep API unchanged.
func (s StarterCreator) Create() {
Debug("StarterCreator.Create")
starterMainPath := filepath.Join(s.thisDir, "..", "main.go")
// Read starter main.go
content, err := os.ReadFile(starterMainPath)
if err != nil {
log.Printf("StarterCreator.Create: failed to read starter main.go at %s: %v", starterMainPath, err)
return
}
// Ensure target directory exists
if err := os.MkdirAll(s.params.ProjectDir, 0o755); err != nil {
log.Printf("StarterCreator.Create: failed to create target directory %s: %v", s.params.ProjectDir, err)
return
}
// Write to <ProjectDir>/main.go
targetPath := filepath.Join(s.params.ProjectDir, "main.go")
must(os.WriteFile(targetPath, content, 0o644))
log.Printf("StarterCreator.Create: wrote starter main.go to %s", targetPath)
s.copyFile("../go.work.template", "go.work")
s.copyFile("../../template.air.toml", ".air.toml")
if s.params.DbType == DataBaseTypeSqlite {
must(os.MkdirAll(filepath.Join(s.params.ProjectDir, "db"), 0o755))
}
s.copySchema()
must(os.MkdirAll(filepath.Join(s.params.ProjectDir, "scripts"), 0o755))
s.copyFile("../../scripts/db-push.sh", "scripts/db-push.sh")
// After copying create_db.sh, run it with the project directory as the root
scriptPath := filepath.Join(s.params.ProjectDir, "scripts", "db-push.sh")
if runtime.GOOS == "windows" {
log.Printf("StarterCreator.Create: skipping create_db.sh execution on Windows")
return
}
if err := os.Chmod(scriptPath, 0o755); err != nil {
log.Printf("StarterCreator.Create: failed to make create_db.sh executable: %v", err)
return
}
cmd := exec.Command("/bin/sh", scriptPath)
cmd.Dir = s.params.ProjectDir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Printf("StarterCreator.Create: failed to run create_db.sh: %v", err)
} else {
log.Printf("StarterCreator.Create: successfully ran create_db.sh in %s", s.params.ProjectDir)
}
}
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))
}
func (s StarterCreator) copySchema() {
content, err := os.ReadFile(filepath.Join(s.thisDir, "../../schema_template.prisma"))
must(err)
if 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, "schema.prisma"), content, 0o644))
}
func must(err error) {
if err != nil {
panic(err)
}
}
+6
View File
@@ -0,0 +1,6 @@
go 1.25.0
use (
.
../ersteller-lib
)