mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-04 00:15:28 +08:00
104 lines
2.5 KiB
Go
104 lines
2.5 KiB
Go
package webui
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"ds2api/internal/config"
|
|
)
|
|
|
|
const (
|
|
defaultBuildTimeout = 5 * time.Minute
|
|
)
|
|
|
|
func EnsureBuiltOnStartup() {
|
|
if !shouldAutoBuild() {
|
|
return
|
|
}
|
|
staticDir := resolveStaticAdminDir(config.StaticAdminDir())
|
|
if hasBuiltUI(staticDir) {
|
|
return
|
|
}
|
|
if err := buildWebUI(staticDir); err != nil {
|
|
config.Logger.Warn("[webui] auto build failed", "error", err)
|
|
return
|
|
}
|
|
if hasBuiltUI(staticDir) {
|
|
config.Logger.Info("[webui] auto build completed", "dir", staticDir)
|
|
return
|
|
}
|
|
config.Logger.Warn("[webui] auto build finished but output missing", "dir", staticDir)
|
|
}
|
|
|
|
func shouldAutoBuild() bool {
|
|
raw := strings.TrimSpace(os.Getenv("DS2API_AUTO_BUILD_WEBUI"))
|
|
if raw == "" {
|
|
return !config.IsVercel()
|
|
}
|
|
switch strings.ToLower(raw) {
|
|
case "1", "true", "yes", "on":
|
|
return true
|
|
case "0", "false", "no", "off":
|
|
return false
|
|
default:
|
|
return !config.IsVercel()
|
|
}
|
|
}
|
|
|
|
func hasBuiltUI(staticDir string) bool {
|
|
if strings.TrimSpace(staticDir) == "" {
|
|
return false
|
|
}
|
|
indexPath := filepath.Join(staticDir, "index.html")
|
|
st, err := os.Stat(indexPath)
|
|
return err == nil && !st.IsDir()
|
|
}
|
|
|
|
func buildWebUI(staticDir string) error {
|
|
if _, err := exec.LookPath("npm"); err != nil {
|
|
return fmt.Errorf("npm not found in PATH: %w", err)
|
|
}
|
|
if strings.TrimSpace(staticDir) == "" {
|
|
return errors.New("static admin dir is empty")
|
|
}
|
|
|
|
config.Logger.Info("[webui] static files missing, running npm build")
|
|
ctx, cancel := context.WithTimeout(context.Background(), defaultBuildTimeout)
|
|
defer cancel()
|
|
|
|
if _, err := os.Stat(filepath.Join("webui", "node_modules")); err != nil {
|
|
if !os.IsNotExist(err) {
|
|
return err
|
|
}
|
|
installCmd := exec.CommandContext(ctx, "npm", "ci", "--prefix", "webui")
|
|
installCmd.Stdout = os.Stdout
|
|
installCmd.Stderr = os.Stderr
|
|
if err := installCmd.Run(); err != nil {
|
|
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
|
return fmt.Errorf("webui npm ci timed out after %s", defaultBuildTimeout)
|
|
}
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := os.MkdirAll(staticDir, 0o755); err != nil {
|
|
return err
|
|
}
|
|
cmd := exec.CommandContext(ctx, "npm", "run", "build", "--prefix", "webui", "--", "--outDir", staticDir, "--emptyOutDir")
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
if err := cmd.Run(); err != nil {
|
|
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
|
return fmt.Errorf("webui build timed out after %s", defaultBuildTimeout)
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|