deno.land / x / esm@v135_2 / server / utils.go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253package server
import ( "context" "encoding/base64" "errors" "fmt" "net" "net/http" "os" "path/filepath" "regexp" "strings" "time"
"github.com/Masterminds/semver/v3" "github.com/ije/esbuild-internal/config" "github.com/ije/esbuild-internal/js_ast" "github.com/ije/esbuild-internal/js_parser" "github.com/ije/esbuild-internal/logger")
const EOL = "\n"
var ( regexpFullVersion = regexp.MustCompile(`^\d+\.\d+\.\d+[\w\.\+\-]*$`) regexpFullVersionPath = regexp.MustCompile(`(\w)@(v?\d+\.\d+\.\d+[\w\.\+\-]*|[0-9a-f]{10})(/|$)`) regexpPathWithVersion = regexp.MustCompile(`\w@[\*\~\^\w\.\+\-]+(/|$|&)`) regexpBuildVersionPath = regexp.MustCompile(`^/v\d+(/|$)`) regexpCliPath = regexp.MustCompile(`^/v\d+\/?$`) regexpLocPath = regexp.MustCompile(`(\.js):\d+:\d+$`) regexpJSIdent = regexp.MustCompile(`^[a-zA-Z_$][\w$]*$`) regexpGlobalIdent = regexp.MustCompile(`__[a-zA-Z]+\$`) regexpVarEqual = regexp.MustCompile(`var ([a-zA-Z]+)\s*=\s*[a-zA-Z]+$`))
var httpClient = &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, DialContext: transportDialContext(&net.Dialer{ Timeout: 10 * time.Second, KeepAlive: 30 * time.Second, }), ForceAttemptHTTP2: true, MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, ResponseHeaderTimeout: 10 * time.Second, TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, },}
func transportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) { return dialer.DialContext}
func fetch(url string) (res *http.Response, err error) { return httpClient.Get(url)}
// isHttpSepcifier returns true if the import path is a remote URL.func isHttpSepcifier(importPath string) bool { return strings.HasPrefix(importPath, "https://") || strings.HasPrefix(importPath, "http://")}
// isLocalSpecifier returns true if the import path is a local path.func isLocalSpecifier(importPath string) bool { return strings.HasPrefix(importPath, "file://") || strings.HasPrefix(importPath, "/") || strings.HasPrefix(importPath, "./") || strings.HasPrefix(importPath, "../") || importPath == "." || importPath == ".."}
func semverLessThan(a string, b string) bool { return semver.MustParse(a).LessThan(semver.MustParse(b))}
// includes returns true if the given string is included in the given array.func includes(a []string, s string) bool { if len(a) == 0 { return false } for _, v := range a { if v == s { return true } } return false}
func filter(a []string, fn func(s string) bool) []string { l := len(a) if l == 0 { return nil } b := make([]string, l) i := 0 for _, v := range a { if fn(v) { b[i] = v i++ } } return b[:i]}
func cloneMap(m map[string]string) map[string]string { n := make(map[string]string, len(m)) for k, v := range m { n[k] = v } return n}
func endsWith(s string, suffixs ...string) bool { for _, suffix := range suffixs { if strings.HasSuffix(s, suffix) { return true } } return false}
func stripModuleExt(s string) string { for _, ext := range jsExts { if strings.HasSuffix(s, ext) { return s[:len(s)-len(ext)] } } return s}
func dirExists(filepath string) bool { fi, err := os.Lstat(filepath) return err == nil && fi.IsDir()}
func fileExists(filepath string) bool { fi, err := os.Lstat(filepath) return err == nil && !fi.IsDir()}
func ensureDir(dir string) (err error) { _, err = os.Lstat(dir) if err != nil && os.IsNotExist(err) { err = os.MkdirAll(dir, 0755) } return}
func findFiles(root string, dir string, fn func(p string) bool) ([]string, error) { rootDir, err := filepath.Abs(root) if err != nil { return nil, err } entries, err := os.ReadDir(rootDir) if err != nil { return nil, err } var files []string for _, entry := range entries { name := entry.Name() path := name if dir != "" { path = dir + "/" + name } if entry.IsDir() { if name == "node_modules" { continue } subFiles, err := findFiles(filepath.Join(rootDir, name), path, fn) if err != nil { return nil, err } n := len(files) files = make([]string, n+len(subFiles)) for i, f := range subFiles { files[i+n] = f } copy(files, subFiles) } else { if fn(path) { files = append(files, path) } } } return files, nil}
func btoaUrl(s string) string { return strings.TrimRight(base64.URLEncoding.EncodeToString([]byte(s)), "=")}
func atobUrl(s string) (string, error) { if l := len(s) % 4; l > 0 { s += strings.Repeat("=", 4-l) } data, err := base64.URLEncoding.DecodeString(s) if err != nil { return "", err } return string(data), nil}
func validateJS(filename string) (isESM bool, namedExports []string, err error) { data, err := os.ReadFile(filename) if err != nil { return } log := logger.NewDeferLog(logger.DeferLogNoVerboseOrDebug, nil) parserOpts := js_parser.OptionsFromConfig(&config.Options{ TS: config.TSOptions{ Parse: endsWith(filename, ".ts", ".mts", ".cts", ".tsx"), }, }) ast, pass := js_parser.Parse(log, logger.Source{ Index: 0, KeyPath: logger.Path{Text: "<stdin>"}, PrettyPath: "<stdin>", Contents: string(data), IdentifierName: "stdin", }, parserOpts) if !pass { err = errors.New("invalid syntax, require javascript/typescript") return } isESM = ast.ExportsKind == js_ast.ExportsESM namedExports = make([]string, len(ast.NamedExports)) i := 0 for name := range ast.NamedExports { namedExports[i] = name i++ } return}
func removeHttpPrefix(s string) (string, error) { for i, v := range s { if v == ':' { return s[i+1:], nil } } return "", fmt.Errorf("colon not found in string: %s", s)}
func concatBytes(a, b []byte) []byte { c := make([]byte, len(a)+len(b)) copy(c, a) copy(c[len(a):], b) return c}
func jsDataUrl(code string) string { return fmt.Sprintf("data:text/javascript;base64,%s", base64.StdEncoding.EncodeToString([]byte(code)))}
Version Info