190 lines
4.2 KiB
Go
190 lines
4.2 KiB
Go
package main
|
|
|
|
//go:generate bash -c "cd app && bun install && bun run build && sed -i 's/\"elysia\": \"^1.3.21\",/\"@sveltejs\\/kit\": \"^2.22.0\",\\n\\t\\t\"elysia\": \"^1.3.21\",/' build/package.json"
|
|
|
|
import (
|
|
"bufio"
|
|
"embed"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"os/signal"
|
|
"path/filepath"
|
|
"runtime"
|
|
"syscall"
|
|
)
|
|
|
|
//go:embed all:app/build
|
|
var buildFiles embed.FS
|
|
|
|
func main() {
|
|
port := os.Getenv("PORT")
|
|
if port == "" {
|
|
port = "3000"
|
|
}
|
|
|
|
homeDir, err := os.UserHomeDir()
|
|
if err != nil {
|
|
log.Fatal("Failed to get home directory:", err)
|
|
}
|
|
bunPath := filepath.Join(homeDir, ".bun", "bin", "bun")
|
|
fmt.Printf("Looking for Bun at: %s\n", bunPath)
|
|
|
|
if _, err := os.Stat(bunPath); os.IsNotExist(err) {
|
|
fmt.Println("Bun runtime not found. Installing Bun...")
|
|
if err := installBun(); err != nil {
|
|
log.Fatal("Failed to install Bun:", err)
|
|
}
|
|
if _, err := os.Stat(bunPath); os.IsNotExist(err) {
|
|
log.Fatal("Bun installation failed - binary not found at:", bunPath)
|
|
}
|
|
fmt.Printf("Bun installed successfully at: %s\n", bunPath)
|
|
} else {
|
|
fmt.Printf("Found existing Bun at: %s\n", bunPath)
|
|
}
|
|
|
|
tempDir, err := os.MkdirTemp("", "craftstation-*")
|
|
if err != nil {
|
|
log.Fatal("Failed to create temp directory:", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
buildFS, err := fs.Sub(buildFiles, "app/build")
|
|
if err != nil {
|
|
log.Fatal("Failed to create sub filesystem:", err)
|
|
}
|
|
|
|
err = extractFiles(buildFS, tempDir)
|
|
if err != nil {
|
|
log.Fatal("Failed to extract files:", err)
|
|
}
|
|
|
|
buildPath := tempDir
|
|
|
|
fmt.Println("Installing dependencies...")
|
|
installCmd := exec.Command(bunPath, "install")
|
|
installCmd.Dir = buildPath
|
|
installCmd.Stdout = os.Stdout
|
|
installCmd.Stderr = os.Stderr
|
|
|
|
if err := installCmd.Run(); err != nil {
|
|
log.Fatal("Failed to install dependencies:", err)
|
|
}
|
|
|
|
cmd := exec.Command(bunPath, "index.js")
|
|
cmd.Dir = buildPath
|
|
cmd.Env = append(os.Environ(),
|
|
"PORT="+port,
|
|
"NODE_ENV=production",
|
|
"FORCE_COLOR=1",
|
|
"BUN_LOG_LEVEL=info",
|
|
)
|
|
|
|
stdout, err := cmd.StdoutPipe()
|
|
if err != nil {
|
|
log.Fatal("Failed to create stdout pipe:", err)
|
|
}
|
|
stderr, err := cmd.StderrPipe()
|
|
if err != nil {
|
|
log.Fatal("Failed to create stderr pipe:", err)
|
|
}
|
|
|
|
fmt.Printf("[Runtime] Craftstation server starting on port %s\n", port)
|
|
fmt.Printf("[Runtime] Open http://localhost:%s in your browser\n", port)
|
|
|
|
sigChan := make(chan os.Signal, 1)
|
|
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
go func() {
|
|
<-sigChan
|
|
fmt.Println("\nShutting down server...")
|
|
if cmd.Process != nil {
|
|
cmd.Process.Signal(syscall.SIGTERM)
|
|
}
|
|
os.Exit(0)
|
|
}()
|
|
|
|
if err := cmd.Start(); err != nil {
|
|
log.Fatal("Failed to start server:", err)
|
|
}
|
|
|
|
go func() {
|
|
scanner := bufio.NewScanner(stdout)
|
|
for scanner.Scan() {
|
|
fmt.Printf("[Webserver] %s\n", scanner.Text())
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
scanner := bufio.NewScanner(stderr)
|
|
for scanner.Scan() {
|
|
fmt.Printf("[Webserver Error] %s\n", scanner.Text())
|
|
}
|
|
}()
|
|
|
|
if err := cmd.Wait(); err != nil {
|
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
|
os.Exit(status.ExitStatus())
|
|
}
|
|
}
|
|
log.Fatal("Server process failed:", err)
|
|
}
|
|
}
|
|
|
|
func installBun() error {
|
|
fmt.Println("Installing Bun runtime...")
|
|
var cmd *exec.Cmd
|
|
|
|
switch runtime.GOOS {
|
|
case "windows":
|
|
cmd = exec.Command("powershell", "-c", "irm bun.sh/install.ps1 | iex")
|
|
case "darwin", "linux":
|
|
cmd = exec.Command("bash", "-c", "curl -fsSL https://bun.sh/install | bash")
|
|
default:
|
|
return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
|
|
}
|
|
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to run Bun installer: %w", err)
|
|
}
|
|
|
|
fmt.Println("Bun installation completed!")
|
|
return nil
|
|
}
|
|
|
|
func extractFiles(fsys fs.FS, destDir string) error {
|
|
return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
destPath := filepath.Join(destDir, path)
|
|
|
|
if d.IsDir() {
|
|
return os.MkdirAll(destPath, 0755)
|
|
}
|
|
|
|
file, err := fsys.Open(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
|
|
destFile, err := os.Create(destPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer destFile.Close()
|
|
|
|
_, err = io.Copy(destFile, file)
|
|
return err
|
|
})
|
|
}
|