@@ -3,11 +3,15 @@ package server
3
3
import (
4
4
"errors"
5
5
"fmt"
6
+ "net/http"
6
7
"net/url"
8
+ "regexp"
7
9
"sort"
8
10
"strings"
11
+ "time"
9
12
10
13
"github.com/Masterminds/semver/v3"
14
+ "github.com/esm-dev/esm.sh/internal/fetch"
11
15
"github.com/esm-dev/esm.sh/internal/npm"
12
16
"github.com/ije/gox/set"
13
17
"github.com/ije/gox/utils"
@@ -70,7 +74,6 @@ func parseEsmPath(npmrc *NpmRC, pathname string) (esm EsmPath, extraQuery string
70
74
err = errors .New ("invalid path" )
71
75
return
72
76
}
73
- exactVersion = true
74
77
hasTargetSegment = validateTargetSegment (strings .Split (subPath , "/" ))
75
78
esm = EsmPath {
76
79
PkgName : pkgName ,
@@ -79,6 +82,17 @@ func parseEsmPath(npmrc *NpmRC, pathname string) (esm EsmPath, extraQuery string
79
82
SubModuleName : stripEntryModuleExt (subPath ),
80
83
PrPrefix : true ,
81
84
}
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
+ }
82
96
return
83
97
}
84
98
@@ -151,69 +165,28 @@ func parseEsmPath(npmrc *NpmRC, pathname string) (esm EsmPath, extraQuery string
151
165
}
152
166
153
167
if ghPrefix {
154
- if npm .IsExactVersion (strings .TrimPrefix (esm .PkgVersion , "v" )) {
168
+ if npm .IsExactVersion (strings .TrimPrefix (esm .PkgVersion , "v" )) || isCommitish ( esm . PkgVersion ) {
155
169
exactVersion = true
156
170
return
157
171
}
158
- var refs [] GitRef
159
- refs , err = listGhRepoRefs ( fmt . Sprintf ( "https://github.com/%s" , esm . PkgName ) )
172
+
173
+ esm . PkgVersion , err = resolveGhPackageVersion ( esm )
160
174
if err != nil {
161
175
return
162
176
}
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
- }
201
177
202
178
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" )
205
180
}
206
-
207
- exactVersion = true
208
181
return
209
182
}
210
183
211
184
originalExactVersion := len (esm .PkgVersion ) > 0 && npm .IsExactVersion (esm .PkgVersion )
212
185
exactVersion = originalExactVersion
213
-
186
+
214
187
// Check if version is a date format (yyyy-mm-dd)
215
188
isDateVersion := npm .IsDateVersion (esm .PkgVersion )
216
-
189
+
217
190
if ! originalExactVersion {
218
191
var p * npm.PackageJSON
219
192
if isDateVersion {
@@ -286,3 +259,79 @@ func isPackageInExternalNamespace(pkgName string, external set.ReadOnlySet[strin
286
259
}
287
260
return false
288
261
}
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