(
name: string,
version: string,
targetType: string,
opts: BuildPublishUrlOptions = {},
)
| 288 | |
| 289 | /** Build a browsable URL for a published package, honouring the configured registry. */ |
| 290 | export function buildPublishUrl( |
| 291 | name: string, |
| 292 | version: string, |
| 293 | targetType: string, |
| 294 | opts: BuildPublishUrlOptions = {}, |
| 295 | ): string | undefined { |
| 296 | switch (targetType) { |
| 297 | case 'npm': { |
| 298 | if (isGitHubPackagesRegistry(opts.registry)) { |
| 299 | // GitHub Packages has no per-version page; link to the package page under the repo. |
| 300 | if (!opts.repoSlug) return undefined; |
| 301 | const unscoped = name.includes('/') ? name.slice(name.indexOf('/') + 1) : name; |
| 302 | return `https://github.com/${opts.repoSlug}/pkgs/npm/${unscoped}`; |
| 303 | } |
| 304 | // Custom/private registries have no canonical browsable URL — avoid a dead npmjs.com link. |
| 305 | if (!isDefaultNpmRegistry(opts.registry)) return undefined; |
| 306 | return `https://www.npmjs.com/package/${name}/v/${version}`; |
| 307 | } |
| 308 | case 'jsr': { |
| 309 | // JSR uses @scope/name format |
| 310 | const parts = name.startsWith('@') ? name.slice(1).split('/') : [name]; |
| 311 | return parts.length === 2 |
| 312 | ? `https://jsr.io/@${parts[0]}/${parts[1]}@${version}` |
| 313 | : `https://jsr.io/${name}@${version}`; |
| 314 | } |
| 315 | default: |
| 316 | return undefined; |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | /** |
| 321 | * Compose a full release body from changelog content + publish status + metadata. |
no test coverage detected
searching dependent graphs…