Add starter creator code
This commit is contained in:
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
go run github.com/steebchen/prisma-client-go db push --skip-generate
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
go 1.25.0
|
||||
|
||||
use (
|
||||
.
|
||||
../ersteller-lib
|
||||
)
|
||||
Reference in New Issue
Block a user