deno.land / x / esm@v135_2 / server / server.go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184package server
import ( "embed" "flag" "fmt" "net/http" "os" "os/exec" "os/signal" "path" "strings" "sync" "syscall"
"github.com/esm-dev/esm.sh/server/config" "github.com/esm-dev/esm.sh/server/storage"
logx "github.com/ije/gox/log" "github.com/ije/rex")
var ( cfg *config.Config cache storage.Cache db storage.DataBase fs storage.FileSystem buildQueue *BuildQueue log *logx.Logger embedFS EmbedFS fetchLocks sync.Map installLocks sync.Map)
type EmbedFS interface { ReadFile(name string) ([]byte, error)}
// Serve serves ESM serverfunc Serve(efs EmbedFS) { var ( cfile string isDev bool err error )
flag.StringVar(&cfile, "config", "config.json", "the config file path") flag.BoolVar(&isDev, "dev", false, "to run server in development mode") flag.Parse()
if !fileExists(cfile) { cfg = config.Default() fmt.Println("Config file not found, use default config") } else { cfg, err = config.Load(cfile) if err != nil { fmt.Println(err.Error()) os.Exit(1) } fmt.Println("Config loaded from", cfile) }
if isDev { cfg.LogLevel = "debug" cwd, err := os.Getwd() if err != nil { fmt.Println(err) os.Exit(1) } embedFS = &devFS{cwd} } else { os.Setenv("NO_COLOR", "1") // disable log color in production embedFS = efs }
log, err = logx.New(fmt.Sprintf("file:%s?buffer=32k", path.Join(cfg.LogDir, fmt.Sprintf("main-v%d.log", VERSION)))) if err != nil { fmt.Printf("initiate logger: %v\n", err) os.Exit(1) } log.SetLevelByName(cfg.LogLevel)
nodeInstallDir := os.Getenv("NODE_INSTALL_DIR") if nodeInstallDir == "" { nodeInstallDir = path.Join(cfg.WorkDir, "nodejs") } nodeVer, pnpmVer, err := checkNodejs(nodeInstallDir) if err != nil { log.Fatalf("check nodejs: %v", err) } if cfg.NpmRegistry == "" { output, err := exec.Command("npm", "config", "get", "registry").CombinedOutput() if err == nil { cfg.NpmRegistry = strings.TrimRight(strings.TrimSpace(string(output)), "/") + "/" } } log.Infof("nodejs: v%s, pnpm: %s, registry: %s", nodeVer, pnpmVer, cfg.NpmRegistry)
err = initCJSLexerWorkDirectory() if err != nil { log.Fatalf("init cjs-lexer: %v", err) }
cache, err = storage.OpenCache(cfg.Cache) if err != nil { log.Fatalf("init storage(cache,%s): %v", cfg.Cache, err) }
fs, err = storage.OpenFS(cfg.Storage) if err != nil { log.Fatalf("init storage(fs,%s): %v", cfg.Storage, err) }
db, err = storage.OpenDB(cfg.Database) if err != nil { log.Fatalf("init storage(db,%s): %v", cfg.Database, err) }
buildQueue = newBuildQueue(int(cfg.BuildConcurrency))
var accessLogger *logx.Logger if cfg.LogDir == "" { accessLogger = &logx.Logger{} } else { accessLogger, err = logx.New(fmt.Sprintf("file:%s?buffer=32k&fileDateFormat=20060102", path.Join(cfg.LogDir, "access.log"))) if err != nil { log.Fatalf("initiate access logger: %v", err) } } accessLogger.SetQuite(true) // quite in terminal
if !cfg.NoCompress { rex.Use(rex.Compression()) } rex.Use( rex.ErrorLogger(log), rex.AccessLogger(accessLogger), rex.Header("Server", "esm.sh"), rex.Cors(rex.CORS{ AllowedOrigins: []string{"*"}, AllowedMethods: []string{ http.MethodGet, http.MethodPost, }, ExposedHeaders: []string{"X-TypeScript-Types"}, AllowCredentials: false, }), auth(cfg.AuthSecret), apiHandler(), esmHandler(), )
C := rex.Serve(rex.ServerConfig{ Port: uint16(cfg.Port), TLS: rex.TLSConfig{ Port: uint16(cfg.TlsPort), AutoTLS: rex.AutoTLSConfig{ AcceptTOS: cfg.TlsPort > 0 && !isDev, CacheDir: path.Join(cfg.WorkDir, "autotls"), }, }, })
log.Infof("Server is ready on http://localhost:%d", cfg.Port)
c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGHUP, syscall.SIGABRT) select { case <-c: case err = <-C: log.Error(err) }
// release resources db.Close() log.FlushBuffer() accessLogger.FlushBuffer()}
func init() { embedFS = &embed.FS{} log = &logx.Logger{}}
Version Info