1- import { generatePackageMarkdown } from '../utils/markdown'
1+ import { generatePackageMarkdown } from '../../ utils/markdown'
22import * as v from 'valibot'
33import { PackageRouteParamsSchema } from '#shared/schemas/package'
44import {
@@ -92,11 +92,11 @@ function isStandardReadme(filename: string | undefined): boolean {
9292 return ! ! filename && standardReadmePattern . test ( filename )
9393}
9494
95- function parsePackageParamsFromPath ( path : string ) : {
95+ function parsePackageParamsFromSlug ( slug : string ) : {
9696 rawPackageName : string
9797 rawVersion : string | undefined
9898} {
99- const segments = path . slice ( 1 ) . split ( '/' ) . filter ( Boolean )
99+ const segments = slug . split ( '/' ) . filter ( Boolean )
100100
101101 if ( segments . length === 0 ) {
102102 return { rawPackageName : '' , rawVersion : undefined }
@@ -127,8 +127,22 @@ function parsePackageParamsFromPath(path: string): {
127127 }
128128}
129129
130- async function handleMarkdownRequest ( packagePath : string ) : Promise < string > {
131- const { rawPackageName, rawVersion } = parsePackageParamsFromPath ( packagePath )
130+ export default defineEventHandler ( async event => {
131+ // Get the slug parameter - Nitro captures it as "slug.md" due to the route pattern
132+ const params = getRouterParams ( event )
133+ const slugParam = params [ 'slug.md' ] || params . slug
134+
135+ if ( ! slugParam ) {
136+ throw createError ( {
137+ statusCode : 404 ,
138+ statusMessage : 'Package not found' ,
139+ } )
140+ }
141+
142+ // Remove .md suffix if present (it will be there from the route)
143+ const slug = slugParam . endsWith ( '.md' ) ? slugParam . slice ( 0 , - 3 ) : slugParam
144+
145+ const { rawPackageName, rawVersion } = parsePackageParamsFromSlug ( slug )
132146
133147 if ( ! rawPackageName ) {
134148 throw createError ( {
@@ -142,7 +156,15 @@ async function handleMarkdownRequest(packagePath: string): Promise<string> {
142156 version : rawVersion ,
143157 } )
144158
145- const packageData = await fetchNpmPackage ( packageName )
159+ let packageData
160+ try {
161+ packageData = await fetchNpmPackage ( packageName )
162+ } catch {
163+ throw createError ( {
164+ statusCode : 502 ,
165+ statusMessage : ERROR_NPM_FETCH_FAILED ,
166+ } )
167+ }
146168
147169 let targetVersion = version
148170 if ( ! targetVersion ) {
@@ -193,63 +215,21 @@ async function handleMarkdownRequest(packagePath: string): Promise<string> {
193215
194216 const repoInfo = parseRepositoryInfo ( packageData . repository )
195217
196- return generatePackageMarkdown ( {
218+ const markdown = generatePackageMarkdown ( {
197219 pkg : packageData ,
198220 version : versionData ,
199221 readme : readmeContent && readmeContent !== NPM_MISSING_README_SENTINEL ? readmeContent : null ,
200222 weeklyDownloads : weeklyDownloadsData ?. downloads ,
201223 dailyDownloads : dailyDownloads ?? undefined ,
202224 repoInfo,
203225 } )
204- }
205226
206- /** Handle .md suffix and Accept: text/markdown header requests */
207- export default defineEventHandler ( async event => {
208- const url = getRequestURL ( event )
209- const path = url . pathname
227+ setHeader ( event , 'Content-Type' , 'text/markdown; charset=utf-8' )
228+ setHeader (
229+ event ,
230+ 'Cache-Control' ,
231+ `public, max-age=${ CACHE_MAX_AGE_ONE_HOUR } , stale-while-revalidate` ,
232+ )
210233
211- if (
212- path . startsWith ( '/api/' ) ||
213- path . startsWith ( '/_' ) ||
214- path . startsWith ( '/__' ) ||
215- path === '/search' ||
216- path . startsWith ( '/search' ) ||
217- path . startsWith ( '/code/' ) ||
218- path === '/' ||
219- path === '/.md'
220- ) {
221- return
222- }
223-
224- const isMarkdownPath = path . endsWith ( '.md' ) && path . length > 3
225- const acceptHeader = getHeader ( event , 'accept' ) ?? ''
226- const wantsMarkdown = acceptHeader . includes ( 'text/markdown' )
227-
228- if ( ! isMarkdownPath && ! wantsMarkdown ) {
229- return
230- }
231-
232- const packagePath = isMarkdownPath ? path . slice ( 0 , - 3 ) : path
233-
234- try {
235- const markdown = await handleMarkdownRequest ( packagePath )
236-
237- setHeader ( event , 'Content-Type' , 'text/markdown; charset=utf-8' )
238- setHeader (
239- event ,
240- 'Cache-Control' ,
241- `public, max-age=${ CACHE_MAX_AGE_ONE_HOUR } , stale-while-revalidate` ,
242- )
243-
244- return markdown
245- } catch ( error : unknown ) {
246- if ( error && typeof error === 'object' && 'statusCode' in error ) {
247- throw error
248- }
249-
250- throw createError ( {
251- statusCode : 502 ,
252- statusMessage : ERROR_NPM_FETCH_FAILED ,
253- } )
254- }
234+ return markdown
255235} )
0 commit comments