@@ -17,9 +17,49 @@ function readFixture(relativePath: string): unknown | null {
1717 }
1818}
1919
20+ /**
21+ * Parse a scoped package name into its components.
22+ * Handles formats like: @scope/name, @scope/name@version, name, name@version
23+ */
24+ function parseScopedPackage ( input : string ) : { name : string ; version ?: string } {
25+ if ( input . startsWith ( '@' ) ) {
26+ // Scoped package: @scope /name or @scope /name@version
27+ const slashIndex = input . indexOf ( '/' )
28+ if ( slashIndex === - 1 ) {
29+ // Invalid format like just "@scope"
30+ return { name : input }
31+ }
32+ const afterSlash = input . slice ( slashIndex + 1 )
33+ const atIndex = afterSlash . indexOf ( '@' )
34+ if ( atIndex === - 1 ) {
35+ // @scope /name (no version)
36+ return { name : input }
37+ }
38+ // @scope /name@version
39+ return {
40+ name : input . slice ( 0 , slashIndex + 1 + atIndex ) ,
41+ version : afterSlash . slice ( atIndex + 1 ) ,
42+ }
43+ }
44+
45+ // Unscoped package: name or name@version
46+ const atIndex = input . indexOf ( '@' )
47+ if ( atIndex === - 1 ) {
48+ return { name : input }
49+ }
50+ return {
51+ name : input . slice ( 0 , atIndex ) ,
52+ version : input . slice ( atIndex + 1 ) ,
53+ }
54+ }
55+
2056function packageToFixturePath ( packageName : string ) : string {
2157 if ( packageName . startsWith ( '@' ) ) {
2258 const [ scope , name ] = packageName . slice ( 1 ) . split ( '/' )
59+ if ( ! name ) {
60+ // Guard against invalid scoped package format like just "@scope"
61+ return `npm-registry/packuments/${ packageName } .json`
62+ }
2363 return `npm-registry/packuments/@${ scope } /${ name } .json`
2464 }
2565 return `npm-registry/packuments/${ packageName } .json`
@@ -294,12 +334,13 @@ async function handleJsdelivrDataApi(route: Route): Promise<boolean> {
294334 // Package file listing: /v1/packages/npm/{package}@{version}
295335 const packageMatch = pathname . match ( / ^ \/ v 1 \/ p a c k a g e s \/ n p m \/ ( .+ ) $ / )
296336 if ( packageMatch ?. [ 1 ] ) {
337+ const parsed = parseScopedPackage ( packageMatch [ 1 ] )
297338 // Return a minimal file tree
298339 await route . fulfill ( {
299340 json : {
300341 type : 'npm' ,
301- name : packageMatch [ 1 ] . split ( '@' ) [ 0 ] ,
302- version : packageMatch [ 1 ] . split ( '@' ) [ 1 ] || 'latest' ,
342+ name : parsed . name ,
343+ version : parsed . version || 'latest' ,
303344 files : [
304345 { name : 'package.json' , hash : 'abc123' , size : 1000 } ,
305346 { name : 'index.js' , hash : 'def456' , size : 500 } ,
@@ -324,7 +365,7 @@ async function handleGravatarApi(route: Route): Promise<boolean> {
324365
325366/**
326367 * Handle GitHub API requests.
327- * Returns mock contributor data for the contributors endpoint.
368+ * Returns mock contributor data from fixtures for the contributors endpoint.
328369 */
329370async function handleGitHubApi ( route : Route ) : Promise < boolean > {
330371 const url = new URL ( route . request ( ) . url ( ) )
@@ -333,30 +374,9 @@ async function handleGitHubApi(route: Route): Promise<boolean> {
333374 // Contributors endpoint: /repos/{owner}/{repo}/contributors
334375 const contributorsMatch = pathname . match ( / ^ \/ r e p o s \/ ( [ ^ / ] + ) \/ ( [ ^ / ] + ) \/ c o n t r i b u t o r s $ / )
335376 if ( contributorsMatch ) {
377+ const fixture = readFixture ( 'github/contributors.json' )
336378 await route . fulfill ( {
337- json : [
338- {
339- login : 'danielroe' ,
340- id : 28706372 ,
341- avatar_url : 'https://avatars.githubusercontent.com/u/28706372?v=4' ,
342- html_url : 'https://github.com/danielroe' ,
343- contributions : 150 ,
344- } ,
345- {
346- login : 'antfu' ,
347- id : 11247099 ,
348- avatar_url : 'https://avatars.githubusercontent.com/u/11247099?v=4' ,
349- html_url : 'https://github.com/antfu' ,
350- contributions : 120 ,
351- } ,
352- {
353- login : 'pi0' ,
354- id : 5158436 ,
355- avatar_url : 'https://avatars.githubusercontent.com/u/5158436?v=4' ,
356- html_url : 'https://github.com/pi0' ,
357- contributions : 100 ,
358- } ,
359- ] ,
379+ json : fixture || [ ] ,
360380 } )
361381 return true
362382 }
0 commit comments