refactor: replace via framework with chi + templ + datastar #2
@@ -1,6 +1,11 @@
|
||||
version: "3"
|
||||
|
||||
tasks:
|
||||
download:
|
||||
desc: Download latest client-side libs
|
||||
cmds:
|
||||
- go run cmd/downloader/main.go
|
||||
|
||||
build:styles:
|
||||
desc: Build TailwindCSS styles
|
||||
cmds:
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
assets/js/datastar.js.map
Normal file
7
assets/js/datastar.js.map
Normal file
File diff suppressed because one or more lines are too long
100
cmd/downloader/main.go
Normal file
100
cmd/downloader/main.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Asset directories, relative to project root.
|
||||
const (
|
||||
jsDir = "assets/js"
|
||||
cssDir = "assets/css"
|
||||
)
|
||||
|
||||
// files maps download URLs to local destination paths.
|
||||
var files = map[string]string{
|
||||
"https://raw.githubusercontent.com/starfederation/datastar/main/bundles/datastar.js": jsDir + "/datastar.js",
|
||||
"https://raw.githubusercontent.com/starfederation/datastar/main/bundles/datastar.js.map": jsDir + "/datastar.js.map",
|
||||
"https://github.com/saadeghi/daisyui/releases/latest/download/daisyui.mjs": cssDir + "/daisyui.mjs",
|
||||
"https://github.com/saadeghi/daisyui/releases/latest/download/daisyui-theme.mjs": cssDir + "/daisyui-theme.mjs",
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
slog.Error("failure", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
dirs := []string{jsDir, cssDir}
|
||||
|
||||
for _, dir := range dirs {
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return fmt.Errorf("create directory %s: %w", dir, err)
|
||||
}
|
||||
}
|
||||
|
||||
return download(files)
|
||||
}
|
||||
|
||||
func download(files map[string]string) error {
|
||||
var wg sync.WaitGroup
|
||||
errCh := make(chan error, len(files))
|
||||
|
||||
for url, dest := range files {
|
||||
wg.Go(func() {
|
||||
base := filepath.Base(dest)
|
||||
slog.Info("downloading...", "file", base, "url", url)
|
||||
if err := downloadFile(url, dest); err != nil {
|
||||
errCh <- fmt.Errorf("download %s: %w", base, err)
|
||||
} else {
|
||||
slog.Info("finished", "file", base)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(errCh)
|
||||
|
||||
var errs []error
|
||||
for err := range errCh {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
func downloadFile(url, dest string) error {
|
||||
resp, err := http.Get(url) //nolint:gosec,noctx // static URLs, simple tool
|
||||
if err != nil {
|
||||
return fmt.Errorf("GET %s: %w", url, err)
|
||||
}
|
||||
defer resp.Body.Close() //nolint:errcheck
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("GET %s: status %s", url, resp.Status)
|
||||
}
|
||||
|
||||
out, err := os.Create(dest) //nolint:gosec // paths are hardcoded constants
|
||||
if err != nil {
|
||||
return fmt.Errorf("create %s: %w", dest, err)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(out, resp.Body); err != nil {
|
||||
out.Close() //nolint:errcheck
|
||||
return fmt.Errorf("write %s: %w", dest, err)
|
||||
}
|
||||
|
||||
if err := out.Close(); err != nil {
|
||||
return fmt.Errorf("close %s: %w", dest, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user