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 named
foo 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/foodepends onbar@workspace*, andbaris version1.2.3, thenfoowill 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 bebar@~1.2.3orbar@^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://<url>[selector]orgit+https://<url>[selector]- Agit+sshorgit+httpsurl 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:#committishAny validcommittishvalue will be checked out. So, shasum, branch, tag, etc., would all work.#semver:<range>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 ofkey:valuepairs. Currently onlypath:<path in repo>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:<registry url>#<name>[@version range or dist-tag]- 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:<name>[@version-range]as a shorthand forregistry:https://registry.npmjs.org/#<name>[@version-range]. -
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:, andgist:are supported by default. -
Anything else will be treated as a
dist-tagin the registry packument. For example,foo@latestorblah@legacy-v2
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',catalogorworkspace. - spec - the full named specifier passed to the constructor
- options - options passed to the constructor, plus defaults
- name - the name portion, so
fooinfoo@1.x - bareSpec - just the part AFTER the name, so
1.xinfoo@1.x - when
type==='git':- gitRemote - git remote url
- gitSelector - the
::-separated set ofkey:valuefields - gitSelectorParsed - the
gitSelectorparsed into a Record object - gitCommittish - the commit sha, branch, or tag
- namedGitHost -
github,gitlab,bitbucket, etc. - 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
type==='registry':- 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
npm:x@2.xor an explicit registry url likeregistry:https://registry.npmjs.org#x@2.x.
- when
type==='file':- file - the path on disk to find the package
- when
type==='remote':- remoteURL - the url to the remote archive
