package cmd import ( "context" "fmt" "io/fs" "net/http" "os" "os/signal" "strconv" "syscall" "time" "github.com/lerko/nib/internal/api" "github.com/spf13/cobra" ) var WebFS fs.FS var ( servePort int serveDev bool ) var serveCmd = &cobra.Command{ Use: "serve", Short: "start the HTTP server", RunE: runServe, } func init() { serveCmd.Flags().IntVar(&servePort, "port", 0, "port to listen on (default 4444)") serveCmd.Flags().BoolVar(&serveDev, "dev", false, "enable CORS for development") rootCmd.AddCommand(serveCmd) } func runServe(_ *cobra.Command, _ []string) error { port := servePort if port == 0 { if envPort := os.Getenv("NIB_PORT"); envPort != "" { p, err := strconv.Atoi(envPort) if err != nil { return fmt.Errorf("invalid NIB_PORT: %w", err) } port = p } else { port = 4444 } } store, err := openStore() if err != nil { return err } defer store.Close() var router = api.NewRouter(store, serveDev) if WebFS != nil { router = api.NewRouter(store, serveDev, WebFS) } addr := fmt.Sprintf(":%d", port) srv := &http.Server{ Addr: addr, Handler: router, } ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() go func() { fmt.Printf("nib serving on %s\n", addr) if serveDev { fmt.Println(" CORS enabled (dev mode)") } if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { fmt.Fprintf(os.Stderr, "server error: %v\n", err) } }() <-ctx.Done() fmt.Println("\nshutting down...") shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() return srv.Shutdown(shutdownCtx) }