
Company News
Socket Joins New OpenJS Program to Fund Node.js Security Work
Socket is joining the OpenJS Security Stewardship Program to fund Node.js vulnerability research, maintainer remediation, and security releases.
@socketregistry/packageurl-js
Advanced tools
TypeScript Package URL (purl) parser and builder.
Drop-in replacement for packageurl-js with full type safety, zero dependencies, and spec compliance with the Package URL specification.
@socketregistry/packageurl-js is the Socket-maintained drop-in replacement for packageurl-js — same API, but ships with built-in TypeScript types, zero runtime dependencies, full purl-spec coverage, and first-class VERS support. It exists because the upstream package lacked types and a maintained tree-shakeable surface; this fork closes both gaps without breaking compatibility.
A Package URL (purl) standardizes how to identify software packages:
pkg:npm/lodash@4.17.21
pkg:pypi/requests@2.28.1
pkg:maven/org.springframework/spring-core@5.3.21
Format breakdown:
pkg:type/namespace/name@version?qualifiers#subpath
│ │ │ │ │ │ │
│ │ │ │ │ │ └─ Optional subpath
│ │ │ │ │ └──────────── Optional key=value pairs
│ │ │ │ └──────────────────── Optional version
│ │ │ └───────────────────────── Required package name
│ │ └─────────────────────────────────── Optional namespace/scope
│ └──────────────────────────────────────── Required package type
└──────────────────────────────────────────── Scheme (always "pkg:")
Supports 40+ ecosystems: npm, pypi, maven, gem, cargo, nuget, composer, golang, docker, and more.
Vers, VersConstraint, VersWildcard)withVersion, withNamespace, withQualifier, withQualifiers, withSubpathtryFromString, tryFromJSON, tryFromObject, isValid, fromUrlpnpm install @socketregistry/packageurl-js
Drop-in replacement via package override:
{
"pnpm": {
"overrides": {
"packageurl-js": "npm:@socketregistry/packageurl-js@^1"
}
}
}
Requirements: Node >= 18.20.8
Parse npm specifiers:
import { parseNpmSpecifier } from '@socketregistry/packageurl-js'
parseNpmSpecifier('lodash@4.17.21')
// -> { namespace: undefined, name: 'lodash', version: '4.17.21' }
parseNpmSpecifier('@babel/core@^7.0.0')
// -> { namespace: '@babel', name: 'core', version: '7.0.0' }
Stringify PURLs:
import { stringify } from '@socketregistry/packageurl-js'
stringify(purl)
// -> 'pkg:npm/lodash@4.17.21'
Compare PURLs:
import { equals, compare } from '@socketregistry/packageurl-js'
equals(purl1, purl2) // -> boolean
compare(purl1, purl2) // -> -1 | 0 | 1
Parse and build:
import { PackageURL } from '@socketregistry/packageurl-js'
// Parse strings
const purl = PackageURL.fromString('pkg:npm/lodash@4.17.21')
console.log(purl.name) // 'lodash'
console.log(purl.version) // '4.17.21'
// Parse npm specifiers
PackageURL.fromNpm('lodash@4.17.21')
PackageURL.fromNpm('@babel/core@^7.0.0')
// Constructor
new PackageURL('npm', null, 'express', '4.18.2')
// -> 'pkg:npm/express@4.18.2'
Builder pattern:
import { PurlBuilder } from '@socketregistry/packageurl-js'
PurlBuilder.npm().name('lodash').version('4.17.21').build()
// -> 'pkg:npm/lodash@4.17.21'
URL conversion:
import { UrlConverter } from '@socketregistry/packageurl-js'
// PackageURL -> URL
UrlConverter.toRepositoryUrl(purl)
// -> 'https://github.com/lodash/lodash'
UrlConverter.toDownloadUrl(purl)
// -> 'https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz'
// URL -> PackageURL
UrlConverter.fromUrl('https://www.npmjs.com/package/lodash')
// -> PackageURL for pkg:npm/lodash
// fromUrl also recognizes distribution (download) URLs and bare paths
UrlConverter.fromUrl(
'/packages/orjson-3.11.9-cp314-cp314-manylinux_2_17_x86_64.whl',
)
// -> PackageURL for pkg:pypi/orjson@3.11.9
fromUrl tries hostname-based parsers first, then falls back to
distribution-filename parsing. The individual parsers are also exposed when you
know the shape:
// Per-ecosystem aggregators (try the ecosystem's known URL shapes)
UrlConverter.fromNpmUrl(url) // registry metadata/tarball or npmjs.com page
UrlConverter.fromPypiUrl(url) // project page or wheel/sdist filename
UrlConverter.fromGemUrl(url) // gem page or .gem / .gemspec.rz
UrlConverter.fromGolangUrl(url) // pkg.go.dev page or module-proxy archive
UrlConverter.fromCargoUrl(url) // crate page or download path
// Distribution (download) URLs/paths, host-independent
UrlConverter.fromDownloadUrl(
'/packages/numpy-2.3.0-cp313-cp313-macosx_11_0_arm64.whl',
)
// -> PackageURL for pkg:pypi/numpy@2.3.0
// Single-shape host parsers: fromGitHubUrl, fromGitlabUrl, fromBitbucketUrl,
// fromComposerUrl, fromHexUrl, fromPubUrl, fromDockerUrl, fromCocoapodsUrl,
// fromHackageUrl, fromCranUrl, fromCondaUrl, fromCpanUrl, fromHuggingfaceUrl,
// fromLuarocksUrl, fromSwiftUrl, fromVscodeMarketplaceUrl, fromOpenVsxUrl
Registry existence checks:
import { purlExists, npmExists } from '@socketregistry/packageurl-js/exists'
// Check if package exists in its registry
await purlExists(purl)
// -> { exists: true, latestVersion: '4.17.21' }
// Type-specific checks (modular)
await npmExists('lodash')
await npmExists('core', '@babel') // scoped package
await npmExists('lodash', undefined, '4.17.21') // validate version
// Supported registries:
// npmExists, pypiExists, cargoExists, gemExists,
// mavenExists, nugetExists, golangExists, packagistExists,
// cocoapodsExists, pubExists, hexExists, cpanExists,
// cranExists, hackageExists, condaExists, dockerExists,
// vscodeExtensionExists
First-class implementation of the VERS companion spec:
import { Vers } from '@socketregistry/packageurl-js'
const range = Vers.parse('vers:npm/>=1.0.0|<2.0.0')
range.contains('1.5.0') // -> true
range.contains('2.0.0') // -> false
PackageURL instances are immutable; with* methods return a new instance:
const next = purl
.withVersion('5.0.0')
.withQualifier('repository_url', 'https://github.com/lodash/lodash')
Parse untrusted input without try/catch:
import { PackageURL } from '@socketregistry/packageurl-js'
const result = PackageURL.tryFromString(userInput)
if (result.isOk()) {
use(result.value)
} else {
log(result.error)
}
PackageURL.isValid(userInput) // -> boolean
PackageURL.fromUrl('https://github.com/lodash/lodash') // infers purl from URL
// fromUrl also recognizes distribution (download) URLs and bare paths:
// wheels, sdists, tarballs, gems, and module-proxy archives.
PackageURL.fromUrl(
'/packages/orjson-3.11.9-cp314-cp314-manylinux_2_17_x86_64.whl',
) // -> pkg:pypi/orjson@3.11.9
All types are exported for maximum flexibility:
import type {
PackageURLObject,
NpmPackageComponents,
ParsedPurlComponents,
QualifiersObject,
ComponentEncoder,
DownloadUrl,
RepositoryUrl,
} from '@socketregistry/packageurl-js'
// Type-safe npm package parsing
const components: NpmPackageComponents = parseNpmSpecifier('lodash@4.17.21')
// Type-safe PURL objects
const obj: PackageURLObject = purl.toObject()
Constants:
import { PurlQualifierNames, PURL_Type } from '@socketregistry/packageurl-js'
// Standard qualifier keys
PurlQualifierNames.Checksum // 'checksum'
PurlQualifierNames.RepositoryUrl // 'repository_url'
// Package types
PURL_Type.NPM // 'npm'
PURL_Type.PYPI // 'pypi'
See docs/types.md for complete type reference.
pnpm install # Install dependencies
pnpm build # Build
pnpm test # Test
pnpm check # Lint + typecheck
MIT
FAQs
Socket.dev optimized package override for packageurl-js
The npm package @socketregistry/packageurl-js receives a total of 8,392 weekly downloads. As such, @socketregistry/packageurl-js popularity was classified as popular.
We found that @socketregistry/packageurl-js demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.

Company News
Socket is joining the OpenJS Security Stewardship Program to fund Node.js vulnerability research, maintainer remediation, and security releases.

Security News
Two compromised GitHub Actions were re-enabled with malicious tags intact, exposing thousands of downstream repositories to Mini Shai-Hulud.

Research
/Security News
A malicious Firefox extension fetches its payload after installation to evade detection, steal Google session cookies, and automate account takeover.