132 lines
4.2 KiB
Go
132 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/evanw/esbuild/pkg/api"
|
|
)
|
|
|
|
func main() {
|
|
// Determine repo root.
|
|
// When invoked via `go generate` from web/, cwd is web/ so we look for go.mod
|
|
// to find the actual module root.
|
|
root, err := findModuleRoot()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Verify vendor files exist
|
|
vendorFiles := []string{
|
|
filepath.Join(root, "web", "vendor", "preact.mjs"),
|
|
filepath.Join(root, "web", "vendor", "preact-hooks.mjs"),
|
|
filepath.Join(root, "web", "vendor", "uplot.esm.js"),
|
|
filepath.Join(root, "web", "vendor", "uplot.css"),
|
|
filepath.Join(root, "web", "vendor", "echarts.esm.js"),
|
|
}
|
|
for _, f := range vendorFiles {
|
|
if _, err := os.Stat(f); os.IsNotExist(err) {
|
|
fmt.Fprintf(os.Stderr, "error: vendor file missing: %s\n", f)
|
|
fmt.Fprintf(os.Stderr, "Run the following to download vendor files:\n")
|
|
fmt.Fprintf(os.Stderr, " mkdir -p web/vendor\n")
|
|
fmt.Fprintf(os.Stderr, " curl -sL https://cdn.jsdelivr.net/npm/preact@10.24.3/dist/preact.module.js -o web/vendor/preact.mjs\n")
|
|
fmt.Fprintf(os.Stderr, " curl -sL https://cdn.jsdelivr.net/npm/preact@10.24.3/hooks/dist/hooks.module.js -o web/vendor/preact-hooks.mjs\n")
|
|
fmt.Fprintf(os.Stderr, " curl -sL https://cdn.jsdelivr.net/npm/uplot@1.6.32/dist/uPlot.esm.js -o web/vendor/uplot.esm.js\n")
|
|
fmt.Fprintf(os.Stderr, " curl -sL https://cdn.jsdelivr.net/npm/uplot@1.6.32/dist/uPlot.min.css -o web/vendor/uplot.css\n")
|
|
fmt.Fprintf(os.Stderr, " curl -sL https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.esm.min.js -o web/vendor/echarts.esm.js\n")
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// Clean + create dist
|
|
distDir := filepath.Join(root, "web", "dist")
|
|
os.RemoveAll(distDir)
|
|
os.MkdirAll(distDir, 0o755)
|
|
|
|
result := api.Build(api.BuildOptions{
|
|
EntryPoints: []string{filepath.Join(root, "web", "src", "main.tsx")},
|
|
Bundle: true,
|
|
Outdir: distDir,
|
|
Format: api.FormatESModule,
|
|
Target: api.ES2020,
|
|
JSX: api.JSXTransform,
|
|
JSXFactory: "h",
|
|
JSXFragment: "Fragment",
|
|
MinifyWhitespace: true,
|
|
MinifyIdentifiers: true,
|
|
MinifySyntax: true,
|
|
Alias: map[string]string{
|
|
"preact": filepath.Join(root, "web", "vendor", "preact.mjs"),
|
|
"preact/hooks": filepath.Join(root, "web", "vendor", "preact-hooks.mjs"),
|
|
"uplot": filepath.Join(root, "web", "vendor", "uplot.esm.js"),
|
|
"echarts": filepath.Join(root, "web", "vendor", "echarts.esm.js"),
|
|
},
|
|
Loader: map[string]api.Loader{
|
|
".css": api.LoaderCSS,
|
|
},
|
|
Splitting: false,
|
|
Write: true,
|
|
LogLevel: api.LogLevelInfo,
|
|
})
|
|
|
|
if len(result.Errors) > 0 {
|
|
for _, e := range result.Errors {
|
|
fmt.Fprintf(os.Stderr, "error: %s\n", e.Text)
|
|
}
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Copy uPlot CSS and favicon
|
|
copyFile(filepath.Join(root, "web", "vendor", "uplot.css"), filepath.Join(distDir, "uplot.css"))
|
|
copyFile(filepath.Join(root, "web", "public", "favicon.svg"), filepath.Join(distDir, "favicon.svg"))
|
|
copyFile(filepath.Join(root, "web", "public", "favicon.svg"), filepath.Join(distDir, "favicon.ico"))
|
|
|
|
// Write index.html
|
|
html := `<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>uopi</title>
|
|
<link rel="icon" href="/favicon.ico" sizes="any" />
|
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
<link rel="stylesheet" href="/uplot.css" />
|
|
<link rel="stylesheet" href="/main.css" />
|
|
</head>
|
|
<body>
|
|
<div id="app"></div>
|
|
<script type="module" src="/main.js"></script>
|
|
</body>
|
|
</html>`
|
|
os.WriteFile(filepath.Join(distDir, "index.html"), []byte(html), 0o644)
|
|
|
|
fmt.Println("Frontend built successfully →", distDir)
|
|
}
|
|
|
|
func copyFile(src, dst string) {
|
|
data, err := os.ReadFile(src)
|
|
if err != nil {
|
|
return // Skip if missing
|
|
}
|
|
os.WriteFile(dst, data, 0o644)
|
|
}
|
|
|
|
// findModuleRoot walks up from cwd until it finds a go.mod file.
|
|
func findModuleRoot() (string, error) {
|
|
dir, err := os.Getwd()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
for {
|
|
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
|
return dir, nil
|
|
}
|
|
parent := filepath.Dir(dir)
|
|
if parent == dir {
|
|
return "", fmt.Errorf("go.mod not found in any parent directory")
|
|
}
|
|
dir = parent
|
|
}
|
|
}
|