Add Go CDN and playground server
Build Core and Handles into in-memory CDN modules, add the marketing site and tutorial docs, and provide a SQLite-backed WebGPU playground with TypeScript tooling and profiling. Amp-Thread-ID: https://ampcode.com/threads/T-01a02485-5574-707c-bff4-5668d83bee8a Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
+108
@@ -0,0 +1,108 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
root, err := repositoryRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("building core and handles packages")
|
||||
packages, err := buildPackages(root)
|
||||
if err != nil {
|
||||
return fmt.Errorf("build packages: %w", err)
|
||||
}
|
||||
log.Printf("loaded %d package assets into memory", len(packages))
|
||||
|
||||
databasePath := os.Getenv("YAWN_DATABASE")
|
||||
if databasePath == "" {
|
||||
databasePath = filepath.Join(root, "server", "data", "yawn.db")
|
||||
}
|
||||
store, err := openPlaygroundStore(databasePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open playground database: %w", err)
|
||||
}
|
||||
defer store.Close()
|
||||
|
||||
app, err := newApplication(
|
||||
store,
|
||||
packages,
|
||||
filepath.Join(root, "node_modules", "monaco-editor", "min"),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = "8080"
|
||||
}
|
||||
server := &http.Server{
|
||||
Addr: ":" + port,
|
||||
Handler: app.routes(),
|
||||
ReadHeaderTimeout: 5 * time.Second,
|
||||
ReadTimeout: 15 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 60 * time.Second,
|
||||
}
|
||||
|
||||
stopped := make(chan os.Signal, 1)
|
||||
signal.Notify(stopped, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-stopped
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
if err := server.Shutdown(ctx); err != nil {
|
||||
log.Printf("shutdown: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Printf("Yawn server listening on http://0.0.0.0:%s", port)
|
||||
err = server.ListenAndServe()
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func repositoryRoot() (string, error) {
|
||||
directory, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for {
|
||||
if fileExists(filepath.Join(directory, "Cargo.toml")) &&
|
||||
fileExists(filepath.Join(directory, "core", "Cargo.toml")) &&
|
||||
fileExists(filepath.Join(directory, "addons", "handles", "package.json")) {
|
||||
return directory, nil
|
||||
}
|
||||
parent := filepath.Dir(directory)
|
||||
if parent == directory {
|
||||
return "", errors.New("could not find the Yawn repository root")
|
||||
}
|
||||
directory = parent
|
||||
}
|
||||
}
|
||||
|
||||
func fileExists(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
return err == nil && !info.IsDir()
|
||||
}
|
||||
Reference in New Issue
Block a user