A PURL (Package URL) parser and serializer, implementing the TC54 PURL specification.
npm install purlpurl [options] <input>input- An npm package specifier or PURL string
--check, -c- Validate the package exists on its registry and show latest version--json- Output only JSON to stdout (no colored PURL output)--help- Show help message--version- Show version number
- If input is a valid PURL string, outputs the normalized PURL on stdout
- If input is an npm package specifier, converts it to a PURL and outputs on stdout
- Parse information (including package URL if available) is output on stderr as JSON
- With
--json, outputs only JSON to stdout (useful for scripting) - Exit code 1 if input is invalid or validation fails
purl [email protected] # outputs pkg:npm/[email protected]
purl @babel/[email protected] # outputs pkg:npm/%40babel/[email protected]
purl express # outputs pkg:npm/express
purl 'pkg:pypi/[email protected]' # outputs pkg:pypi/[email protected]
purl -c [email protected] # validates package exists, then outputs PURLnpm, pypi, gem, cargo, nuget, hex, maven, composer, pub, hackage, cocoapods
import {
PURL,
parse,
stringify,
valid,
normalize,
eq,
compare,
type,
namespace,
name,
version,
qualifiers,
subpath,
fromNPM,
url,
validate,
validateTypes,
} from 'purl';import PURL from 'purl/purl';
const purl = new PURL('pkg:npm/[email protected]');
purl.type; // 'npm'
purl.namespace; // null
purl.name; // 'lodash'
purl.version; // '4.17.21'
purl.qualifiers; // null
purl.subpath; // null
String(purl); // 'pkg:npm/[email protected]'
// From components
const purl2 = new PURL({
type: 'npm',
namespace: '@babel',
name: 'core',
version: '7.0.0',
});
String(purl2); // 'pkg:npm/%40babel/[email protected]'
// Instance methods
purl.equals(other); // boolean
purl.compare(other); // -1 | 0 | 1Parse a PURL string into a PURL object. Returns null if invalid.
import parse from 'purl/parse';
parse('pkg:npm/[email protected]'); // PURL instance
parse('invalid'); // nullConvert PURL components to a canonical PURL string.
import stringify from 'purl/stringify';
stringify({ type: 'npm', name: 'lodash', version: '4.17.21' });
// 'pkg:npm/[email protected]'Returns the normalized PURL string if valid, null otherwise.
import valid from 'purl/valid';
valid('pkg:NPM/[email protected]'); // 'pkg:npm/[email protected]'
valid('invalid'); // nullNormalize a PURL string. Throws if invalid.
import normalize from 'purl/normalize';
normalize('pkg:NPM/[email protected]'); // 'pkg:npm/[email protected]'
normalize('invalid'); // throwsCompare two PURLs for equality.
import eq from 'purl/eq';
eq('pkg:npm/[email protected]', 'pkg:NPM/[email protected]'); // true
eq('pkg:npm/[email protected]', 'pkg:npm/[email protected]'); // falseCompare two PURLs for sorting. Returns -1, 0, or 1.
import compare from 'purl/compare';
['pkg:npm/bbb', 'pkg:npm/aaa'].sort(compare);
// ['pkg:npm/aaa', 'pkg:npm/bbb']Each accessor returns the component value or null if invalid/missing.
import type from 'purl/type';
import namespace from 'purl/namespace';
import name from 'purl/name';
import version from 'purl/version';
import qualifiers from 'purl/qualifiers';
import subpath from 'purl/subpath';
type('pkg:npm/[email protected]'); // 'npm'
namespace('pkg:npm/%40babel/core'); // '@babel'
name('pkg:npm/[email protected]'); // 'lodash'
version('pkg:npm/[email protected]'); // '4.17.21'
qualifiers('pkg:npm/foo?a=b'); // { a: 'b' }
subpath('pkg:npm/foo#lib/index.js'); // 'lib/index.js'Convert an npm package specifier to a PURL object.
import fromNPM from 'purl/from-npm';
fromNPM('[email protected]'); // PURL for pkg:npm/[email protected]
fromNPM('@babel/[email protected]'); // PURL for pkg:npm/%40babel/[email protected]
fromNPM('lodash@^4.0.0'); // PURL for pkg:npm/lodash (no version for ranges)Get the registry URL for a PURL.
import url from 'purl/url';
url('pkg:npm/[email protected]'); // 'https://www.npmjs.com/package/lodash/v/4.17.21'
url('pkg:pypi/[email protected]'); // 'https://pypi.org/project/requests/2.28.0/'
url('pkg:github/ljharb/[email protected]'); // 'https://github.com/ljharb/qs/tree/6.11.0'bioconductor, bitbucket, cargo, chrome, clojars, cocoapods, composer, conan, conda, cpan, deno, docker, elm, gem, github, golang, hackage, hex, homebrew, huggingface, luarocks, maven, npm, nuget, pub, pypi, swift, vscode
Validate a PURL against its package registry. Returns a promise.
import validate, { supportedTypes } from 'purl/validate';
const result = await validate('pkg:npm/[email protected]');
// { valid: true, latestVersion: '4.17.21' }
const result2 = await validate('pkg:npm/nonexistent-package-xyz');
// { valid: false, error: 'Package "nonexistent-package-xyz" not found on npm', latestVersion: null }
supportedTypes; // ['npm', 'pypi', 'gem', 'cargo', 'nuget', 'hex', 'maven', 'composer', 'pub', 'hackage', 'cocoapods']Clone the repo, npm install, and run npm test.
Prior to v2, purl was a different package.
v0 was just a placeholder, but v1 can be found both on archive.org and on the original branch of this repo.
