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>
109 lines
2.3 KiB
Go
109 lines
2.3 KiB
Go
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()
|
|
}
|