@@ -3,11 +3,15 @@ package server
33import (
44 "errors"
55 "fmt"
6+ "net/http"
67 "net/url"
8+ "regexp"
79 "sort"
810 "strings"
11+ "time"
912
1013 "github.com/Masterminds/semver/v3"
14+ "github.com/esm-dev/esm.sh/internal/fetch"
1115 "github.com/esm-dev/esm.sh/internal/npm"
1216 "github.com/ije/gox/set"
1317 "github.com/ije/gox/utils"
@@ -70,7 +74,6 @@ func parseEsmPath(npmrc *NpmRC, pathname string) (esm EsmPath, extraQuery string
7074 err = errors .New ("invalid path" )
7175 return
7276 }
73- exactVersion = true
7477 hasTargetSegment = validateTargetSegment (strings .Split (subPath , "/" ))
7578 esm = EsmPath {
7679 PkgName : pkgName ,
@@ -79,6 +82,17 @@ func parseEsmPath(npmrc *NpmRC, pathname string) (esm EsmPath, extraQuery string
7982 SubModuleName : stripEntryModuleExt (subPath ),
8083 PrPrefix : true ,
8184 }
85+ if isCommitish (esm .PkgVersion ) {
86+ exactVersion = true
87+ return
88+ }
89+ esm .PkgVersion , err = resolvePrPackageVersion (esm )
90+ if err != nil {
91+ return
92+ }
93+ if ! isCommitish (esm .PkgVersion ) {
94+ err = errors .New ("pkg.pr.new: tag or branch not found" )
95+ }
8296 return
8397 }
8498
@@ -151,69 +165,28 @@ func parseEsmPath(npmrc *NpmRC, pathname string) (esm EsmPath, extraQuery string
151165 }
152166
153167 if ghPrefix {
154- if npm .IsExactVersion (strings .TrimPrefix (esm .PkgVersion , "v" )) {
168+ if npm .IsExactVersion (strings .TrimPrefix (esm .PkgVersion , "v" )) || isCommitish ( esm . PkgVersion ) {
155169 exactVersion = true
156170 return
157171 }
158- var refs [] GitRef
159- refs , err = listGhRepoRefs ( fmt . Sprintf ( "https://github.com/%s" , esm . PkgName ) )
172+
173+ esm . PkgVersion , err = resolveGhPackageVersion ( esm )
160174 if err != nil {
161175 return
162176 }
163- if esm .PkgVersion == "" {
164- for _ , ref := range refs {
165- if ref .Ref == "HEAD" {
166- esm .PkgVersion = ref .Sha [:7 ]
167- return
168- }
169- }
170- } else {
171- // try to find the exact tag or branch
172- for _ , ref := range refs {
173- if ref .Ref == "refs/tags/" + esm .PkgVersion || ref .Ref == "refs/heads/" + esm .PkgVersion {
174- esm .PkgVersion = ref .Sha [:7 ]
175- return
176- }
177- }
178- // try to find the 'semver' tag
179- if semv , erro := semver .NewConstraint (strings .TrimPrefix (esm .PkgVersion , "semver:" )); erro == nil {
180- semtags := make ([]* semver.Version , len (refs ))
181- i := 0
182- for _ , ref := range refs {
183- if strings .HasPrefix (ref .Ref , "refs/tags/" ) {
184- v , e := semver .NewVersion (strings .TrimPrefix (ref .Ref , "refs/tags/" ))
185- if e == nil && semv .Check (v ) {
186- semtags [i ] = v
187- i ++
188- }
189- }
190- }
191- if i > 0 {
192- semtags = semtags [:i ]
193- if i > 1 {
194- sort .Sort (semver .Collection (semtags ))
195- }
196- esm .PkgVersion = semtags [i - 1 ].String ()
197- return
198- }
199- }
200- }
201177
202178 if ! isCommitish (esm .PkgVersion ) {
203- err = errors .New ("git: tag or branch not found" )
204- return
179+ err = errors .New ("github: tag or branch not found" )
205180 }
206-
207- exactVersion = true
208181 return
209182 }
210183
211184 originalExactVersion := len (esm .PkgVersion ) > 0 && npm .IsExactVersion (esm .PkgVersion )
212185 exactVersion = originalExactVersion
213-
186+
214187 // Check if version is a date format (yyyy-mm-dd)
215188 isDateVersion := npm .IsDateVersion (esm .PkgVersion )
216-
189+
217190 if ! originalExactVersion {
218191 var p * npm.PackageJSON
219192 if isDateVersion {
@@ -286,3 +259,79 @@ func isPackageInExternalNamespace(pkgName string, external set.ReadOnlySet[strin
286259 }
287260 return false
288261}
262+
263+ func resolveGhPackageVersion (esm EsmPath ) (version string , err error ) {
264+ return withCache ("gh/" + esm .PkgName + "@" + esm .PkgVersion , time .Duration (config .NpmQueryCacheTTL )* time .Second , func () (version string , aliasKey string , err error ) {
265+ var refs []GitRef
266+ refs , err = listGhRepoRefs (fmt .Sprintf ("https://github.com/%s" , esm .PkgName ))
267+ if err != nil {
268+ return
269+ }
270+ if esm .PkgVersion == "" {
271+ for _ , ref := range refs {
272+ if ref .Ref == "HEAD" {
273+ version = ref .Sha [:7 ]
274+ return
275+ }
276+ }
277+ } else {
278+ // try to find the exact tag or branch
279+ for _ , ref := range refs {
280+ if ref .Ref == "refs/tags/" + esm .PkgVersion || ref .Ref == "refs/heads/" + esm .PkgVersion {
281+ version = ref .Sha [:7 ]
282+ return
283+ }
284+ }
285+ // try to find the 'semver' tag
286+ if semv , erro := semver .NewConstraint (strings .TrimPrefix (esm .PkgVersion , "semver:" )); erro == nil {
287+ semtags := make ([]* semver.Version , len (refs ))
288+ i := 0
289+ for _ , ref := range refs {
290+ if after , ok := strings .CutPrefix (ref .Ref , "refs/tags/" ); ok {
291+ v , e := semver .NewVersion (after )
292+ if e == nil && semv .Check (v ) {
293+ semtags [i ] = v
294+ i ++
295+ }
296+ }
297+ }
298+ if i > 0 {
299+ semtags = semtags [:i ]
300+ if i > 1 {
301+ sort .Sort (semver .Collection (semtags ))
302+ }
303+ version = semtags [i - 1 ].String ()
304+ return
305+ }
306+ }
307+ }
308+ version = esm .PkgVersion
309+ return
310+ })
311+ }
312+
313+ func resolvePrPackageVersion (esm EsmPath ) (version string , err error ) {
314+ return withCache ("pr/" + esm .PkgName + "@" + esm .PkgVersion , time .Duration (config .NpmQueryCacheTTL )* time .Second , func () (version string , aliasKey string , err error ) {
315+ u , err := url .Parse (fmt .Sprintf ("https://pkg.pr.new/%s@%s" , esm .PkgName , esm .PkgVersion ))
316+ if err != nil {
317+ return
318+ }
319+ versionRegex := regexp .MustCompile (`[^/]@([\da-f]{7,})$` )
320+ client , recycle := fetch .NewClient ("esmd/" + VERSION , 30 , false , nil )
321+ version = esm .PkgVersion
322+ client .CheckRedirect = func (req * http.Request , via []* http.Request ) error {
323+ match := versionRegex .FindStringSubmatch (req .URL .Path )
324+ if len (match ) > 1 {
325+ version = match [1 ][:7 ]
326+ }
327+ if len (via ) >= 6 {
328+ return errors .New ("too many redirects" )
329+ }
330+ return nil
331+ }
332+ defer recycle ()
333+
334+ _ , err = client .Fetch (u , nil )
335+ return
336+ })
337+ }
0 commit comments