Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions server/utils/readme-loaders.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import * as v from 'valibot'
import { PackageRouteParamsSchema } from '#shared/schemas/package'
import { CACHE_MAX_AGE_ONE_HOUR, NPM_MISSING_README_SENTINEL } from '#shared/utils/constants'
import {
CACHE_MAX_AGE_ONE_HOUR,
NPM_MISSING_README_SENTINEL,
NPM_README_TRUNCATION_THRESHOLD,
} from '#shared/utils/constants'

/** Standard README filenames to try when fetching from jsdelivr (case-sensitive CDN) */
const standardReadmeFilenames = [
Expand Down Expand Up @@ -75,11 +79,16 @@ export const resolvePackageReadmeSource = defineCachedFunction(

const hasValidNpmReadme = readmeContent && readmeContent !== NPM_MISSING_README_SENTINEL

if (!hasValidNpmReadme || !isStandardReadme(readmeFilename)) {
if (
!hasValidNpmReadme ||
!isStandardReadme(readmeFilename) ||
readmeContent!.length >= NPM_README_TRUNCATION_THRESHOLD
) {
const resolvedVersion = version ?? packageData['dist-tags']?.latest
const jsdelivrReadme = await fetchReadmeFromJsdelivr(
packageName,
standardReadmeFilenames,
version,
resolvedVersion,
)
if (jsdelivrReadme) {
readmeContent = jsdelivrReadme
Expand Down
2 changes: 2 additions & 0 deletions shared/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export const ERROR_PACKAGE_REQUIREMENTS_FAILED =
export const ERROR_FILE_LIST_FETCH_FAILED = 'Failed to fetch file list.'
export const ERROR_CALC_INSTALL_SIZE_FAILED = 'Failed to calculate install size.'
export const NPM_MISSING_README_SENTINEL = 'ERROR: No README data found!'
/** The npm registry truncates the packument readme field at 65,536 characters (2^16) */
export const NPM_README_TRUNCATION_THRESHOLD = 64_000
export const ERROR_JSR_FETCH_FAILED = 'Failed to fetch package from JSR registry.'
export const ERROR_NPM_FETCH_FAILED = 'Failed to fetch package from npm registry.'
export const ERROR_PROVENANCE_FETCH_FAILED = 'Failed to fetch provenance.'
Expand Down
23 changes: 23 additions & 0 deletions test/unit/server/utils/readme-loaders.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,29 @@ describe('resolvePackageReadmeSource', () => {
})
})

it('fetches from jsdelivr when packument readme exceeds truncation threshold', async () => {
const truncatedReadme = 'x'.repeat(64_000)
const fullReadme = 'x'.repeat(80_000)
fetchNpmPackageMock.mockResolvedValue({
'readme': truncatedReadme,
'readmeFilename': 'README.md',
'repository': undefined,
'versions': {},
'dist-tags': { latest: '1.0.0' },
})
parseRepositoryInfoMock.mockReturnValue(undefined)
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
text: async () => fullReadme,
})
vi.stubGlobal('fetch', fetchMock)

const result = await resolvePackageReadmeSource('pkg')

expect(result).toMatchObject({ markdown: fullReadme })
expect(fetchMock).toHaveBeenCalled()
})

it('uses package repository for repoInfo when markdown is present', async () => {
fetchNpmPackageMock.mockResolvedValue({
readme: '# Hi',
Expand Down
Loading