Package specifier library
npm install @vltpkg/spec!spec
This is a library for parsing package specifiers.
Namings ·
Specifiers · Usage ·
Properties
Specifiers are primarily used in the following cases:
- On the command line, like vlt add foo@1.x
- In manifests (such as package.json) where dependencies are listed,
like "dependencies": { "foo": "1.x" }
- Internally within vlt, such as lockfiles and so on.
A "named" specifier is one with the full name included, separated from
the specifier by a @ character, such as foo@1.x or@vltpkg/spec@1.0.0. The name in these cases would be foo and@vltpkg/spec, respectively.
Note that it does _not_ always correspond to the "name" in the
manifest of the resolved package! For example, foo@npm:react@latest
would resolve to the latest version of react, but would be namedfoo in the dependency graph, and loaded as import('foo').
The following specifier types are supported:
- workspace:... - Provide a semver range, or one of ~, *, or ^
to match against a dependency that exists in a workspace project of
a monorepo. The package name _must_ exist as a workspace project in
the monorepo. If a semver range is provided, then it must match the
referenced workspace package version. Otherwise:
- * - Fill in whatever version is in the workspace, without any
prefix. So, if ./packages/foo depends on bar@workspace*, and
bar is version 1.2.3, then foo will be published with
{ "dependencies": { "bar": "1.2.3" }}
- ~ or ^ - Publish with the version found in the monorepo,
prefixed by the character. So in the example above, it'd be
bar@~1.2.3 or bar@^1.2.3, respectively.
- semver range - A valid semver range (including the empty string or
a single semver version). This is resolved against the default
registry. If the spec is a valid semver range, then no further
parsing is done.
- git+ssh:// or git+https:// - A
git+ssh or git+https url will be checked out by git. If no 'git
selector' is provided, then it will attempt to install from the
default version. The git selector can be:
- #committish Any valid committish value will be checked out.
So, shasum, branch, tag, etc., would all work.
- #semver: If a semver range is provided, it will select
over all the tags that are valid semver versions, and pick the
highest version number that satisfies the range.
- Additional fields can be specified by a ::-separated series of
key:value pairs. Currently only path: is
supported, for referencing packages living below the root of the
repository, as in a monorepo. For example,
tcompare@github:tapjs/tapjs#bf457f24::path:src/tcompare
- https://some-host.com/path/to/file.tgz - An https or http URL to a
tarball will resolve to itself.
- file:///path/to/file - A file URL will resolve to itself. If it is
a directory, it will be reified as a symbolic link to the folder
specified. If it is a file, it will be treated as a tarball that
gets unpacked into place. Relative paths are resolved from the
package with the dependency.
- registry: - This
will use the specified registry url, and look up the name and
version on that registry.
- If a registry shorthand is defined in the options, then you can use
it as an alias for that registry. Currently, the only shorthand that
is enabled by default is npm: as a shorthand
for registry:https://registry.npmjs.org/#.
- If a git repository shorthand is defined in the options, then you
can use that shorthand prefix as an alias for that git host.
Currently, github:, bitbucket:, gitlab:, and gist: are
supported by default.
- Anything else will be treated as a dist-tag in the registry
packument. For example, foo@latest or blah@legacy-v2
``js
import { Spec, type SpecOptions } from '@vltpkg/spec'
// optional: create some registry shorthands
const opts: SpecOptions = {
registries: {
// internal company registry or something
acmereg: 'https://dev.acme.internal/npm',
},
gitHosts: {
github: 'git+ssh://git@github.com:$1/$2',
// the $# pieces here are replaced by the path-separated
// portions, so eg github:user/project#whatever
acmegit: 'git+ssh://git@dev.acme.internal/git/$1/$2/$3',
}
}
const lodash = Spec.parse('lodash@latest')
// which is the same as:
const lodash = Spec.parse('lodash@npm:lodash@latest')
// which is the same as:
const lodash = Spec.parse(
'lodash@registry:https://registry.npmjs.org/#lodash@latest'
)
// pull from github
const ghProject = Spec.parse('abbrev@github:npm/abbrev-js#main', opts)
// pull from GitHub package registry
const ghPackage = Spec.parse(
'@octocat/hello-world',
'gh:@octocat/hello-world@1.0.0',
opts,
)
// pull from our internal hosts using the acme shorthand names
const fooFromAcmeReg = Spec.parse('foo@acmereg:foo@1.2', opts)
const fooFromAcmeReg = Spec.parse(
'foo@acmegit:department/team/monorepo#main;directory:packages/foo',
opts,
)
``
- type - the type of spec that this is. One of 'registry', 'git','file'
, 'remote', catalog or workspace.foo
- spec - the full named specifier passed to the constructor
- options - options passed to the constructor, plus defaults
- name - the name portion, so in foo@1.x1.x
- bareSpec - just the part AFTER the name, so in foo@1.xtype
- when === 'git':::
- gitRemote - git remote url
- gitSelector - the -separated set of key:value fieldsgitSelector
- gitSelectorParsed - the parsed into a Record objectgithub
- gitCommittish - the commit sha, branch, or tag
- namedGitHost - , gitlab, bitbucket, etc.type
- remoteURL - when using a named git host with an archive url
template, and a committish is provided, this is the url to
download a tarball archive
- semver - the semver range, if provided in the gitSelector
- range - the parsed semver range, if valid
- when === 'registry':npm:x@2.x
- registry - the registry to look up data from
- namedRegistry - in the case of alias specs, the named registry
- registrySpec - the semver range or dist-tag
- semver - the semver range, if valid
- range - the parsed semver range, if valid
- distTag - the registrySpec when it is not a semver range
- subspec - the parsed spec to to be resolved against the registry
in question, if the spec is a named registry like orregistry:https://registry.npmjs.org#x@2.x
an explicit registry url like
.type
- when === 'file':type
- file - the path on disk to find the package
- when === 'remote'`:
- remoteURL - the url to the remote archive