Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface URLBuilder {
registry(name: string, version?: string): string
download(name: string, version: string): string
documentation(name: string, version?: string): string
readme(name: string, version?: string): string
purl(name: string, version?: string): string
}

Expand Down
9 changes: 9 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,12 @@ export function selectVersion(versions: Version[], options?: {
export function resolveDocsUrl(pkg: Package, urls: URLBuilder, version?: string): string {
return pkg.documentation || pkg.homepage || urls.documentation(pkg.name, version)
}

/**
* Resolve the best README URL for a package.
*
* Returns the ecosystem-specific URL where the package README can be fetched.
*/
export function resolveReadmeUrl(pkg: Package, urls: URLBuilder, version?: string): string {
return urls.readme(pkg.name, version)
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export {
bulkFetchPackages,
selectVersion,
resolveDocsUrl,
resolveReadmeUrl,
} from './helpers.ts'

// Types
Expand Down
5 changes: 5 additions & 0 deletions src/registries/cargo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ class CargoRegistry implements Registry {
documentation: (name: string, version?: string) => {
return version ? `https://docs.rs/${name}/${version}` : `https://docs.rs/${name}`
},
readme: (name: string, version?: string) => {
return version
? `https://crates.io/api/v1/crates/${name}/${version}/readme`
: `https://crates.io/api/v1/crates/${name}/readme`
},
purl: (name: string, version?: string) => {
const versionSuffix = version ? `@${version}` : ''
return `pkg:cargo/${name}${versionSuffix}`
Expand Down
4 changes: 4 additions & 0 deletions src/registries/npm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ class NpmRegistry implements Registry {
documentation: (name: string, _version?: string) => {
return `https://www.npmjs.com/package/${name}`
},
readme: (name: string, version?: string) => {
const ver = version ? `@${version}` : ''
return `https://cdn.jsdelivr.net/npm/${name}${ver}/README.md`
},
purl: (name: string, version?: string) => {
const versionSuffix = version ? `@${version}` : ''
return `pkg:npm/${name}${versionSuffix}`
Expand Down
4 changes: 4 additions & 0 deletions src/registries/packagist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ class PackagistRegistry implements Registry {
const [vendor, pkg] = this.parseName(name)
return `https://packagist.org/packages/${vendor}/${pkg}`
},
readme: (name: string, _version?: string) => {
const [vendor, pkg] = this.parseName(name)
return `https://packagist.org/packages/${vendor}/${pkg}`
},
purl: (name: string, version?: string) => {
const versionSuffix = version ? `@${version}` : ''
return `pkg:composer/${name}${versionSuffix}`
Expand Down
6 changes: 6 additions & 0 deletions src/registries/pypi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@ class PyPIRegistry implements Registry {
const normalized = this.normalizeName(name)
return `https://pypi.org/project/${normalized}`
},
readme: (name: string, version?: string) => {
const normalized = this.normalizeName(name)
return version
? `https://pypi.org/project/${normalized}/${version}/`
: `https://pypi.org/project/${normalized}/`
},
purl: (name: string, version?: string) => {
const normalized = this.normalizeName(name)
const versionSuffix = version ? `@${version}` : ''
Expand Down
4 changes: 4 additions & 0 deletions src/registries/rubygems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ class RubyGemsRegistry implements Registry {
const versionSuffix = version ? `/${version}` : ''
return `https://www.rubydoc.info/gems/${name}${versionSuffix}`
},
readme: (name: string, version?: string) => {
const base = `https://rubygems.org/gems/${name}`
return version ? `${base}/versions/${version}` : base
},
purl: (name: string, version?: string) => {
const versionSuffix = version ? `@${version}` : ''
return `pkg:gem/${name}${versionSuffix}`
Expand Down
1 change: 1 addition & 0 deletions test/unit/cached-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ function createMockRegistry(ecosystem: string, overrides?: Partial<Registry>): R
registry: () => `https://${ecosystem}.example.com`,
download: () => `https://${ecosystem}.example.com/download`,
documentation: () => `https://${ecosystem}.example.com/docs`,
readme: () => `https://${ecosystem}.example.com/readme`,
purl: () => `pkg:${ecosystem}/`,
}),
fetchPackage: async () => ({
Expand Down
20 changes: 19 additions & 1 deletion test/unit/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Package, Version, URLBuilder } from '../../src/core/types.ts'
import { selectVersion, resolveDocsUrl } from '../../src/helpers.ts'
import { selectVersion, resolveDocsUrl, resolveReadmeUrl } from '../../src/helpers.ts'

function version(num: string, status: '' | 'yanked' | 'deprecated' | 'retracted' = '', date = '2024-01-01T00:00:00Z'): Version {
return {
Expand Down Expand Up @@ -32,6 +32,7 @@ const stubUrls: URLBuilder = {
registry: () => '',
download: () => '',
documentation: (name: string, ver?: string) => `https://docs.example.com/${name}/${ver ?? 'latest'}`,
readme: (name: string, ver?: string) => `https://readme.example.com/${name}/${ver ?? 'latest'}`,
purl: () => '',
}

Expand Down Expand Up @@ -135,3 +136,20 @@ describe('resolveDocsUrl', () => {
expect(resolveDocsUrl(p, stubUrls)).toBe('https://docs.rs/serde')
})
})

describe('resolveReadmeUrl', () => {
it('returns ecosystem-specific readme URL with version', () => {
const p = pkg()
expect(resolveReadmeUrl(p, stubUrls, '1.0.0')).toBe('https://readme.example.com/test/1.0.0')
})

it('returns ecosystem-specific readme URL without version', () => {
const p = pkg()
expect(resolveReadmeUrl(p, stubUrls)).toBe('https://readme.example.com/test/latest')
})

it('uses package name for URL construction', () => {
const p = pkg({ name: 'serde' })
expect(resolveReadmeUrl(p, stubUrls, '1.0.220')).toBe('https://readme.example.com/serde/1.0.220')
})
})
9 changes: 9 additions & 0 deletions test/unit/registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe('registry', () => {
registry: () => '',
download: () => '',
documentation: () => '',
readme: () => '',
purl: () => '',
}),
})
Expand Down Expand Up @@ -55,6 +56,7 @@ describe('registry', () => {
registry: () => '',
download: () => '',
documentation: () => '',
readme: () => '',
purl: () => '',
}),
})
Expand Down Expand Up @@ -87,6 +89,7 @@ describe('registry', () => {
registry: () => '',
download: () => '',
documentation: () => '',
readme: () => '',
purl: () => '',
}),
})
Expand Down Expand Up @@ -134,6 +137,7 @@ describe('registry', () => {
registry: () => baseURL,
download: () => '',
documentation: () => '',
readme: () => '',
purl: () => '',
}),
})
Expand Down Expand Up @@ -164,6 +168,7 @@ describe('registry', () => {
registry: () => baseURL,
download: () => '',
documentation: () => '',
readme: () => '',
purl: () => '',
}),
})
Expand Down Expand Up @@ -196,6 +201,7 @@ describe('registry', () => {
registry: () => '',
download: () => '',
documentation: () => '',
readme: () => '',
purl: () => '',
}),
})
Expand Down Expand Up @@ -236,6 +242,7 @@ describe('registry', () => {
registry: () => '',
download: () => '',
documentation: () => '',
readme: () => '',
purl: () => '',
}),
})
Expand Down Expand Up @@ -269,6 +276,7 @@ describe('registry', () => {
registry: () => '',
download: () => '',
documentation: () => '',
readme: () => '',
purl: () => '',
}),
})
Expand Down Expand Up @@ -302,6 +310,7 @@ describe('registry', () => {
registry: () => '',
download: () => '',
documentation: () => '',
readme: () => '',
purl: () => '',
}),
})
Expand Down