Help us shape the future of Go! Take the 2026 Go Developer Survey

npm

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package npm is the format of npm repositories (decision 0034). It reads each tarball's package.json, indexes a tarball at its canonical path as a version of its package (decision 0018) with the per-version Metadata that packuments and search are built from, and keeps the npm.* properties. Every write reaches it through the item service, so a tarball deployed by npm publish, by jf npm publish's REST deploy, or landed by a copy, a move or a restore is indexed the same way.

A .tgz anywhere else, or one without a readable package.json, is stored but not indexed: every repository has strict layout (DV-041).

Index

Constants

View Source
const (
	PropName        = "npm.name"
	PropVersion     = "npm.version"
	PropDescription = "npm.description"
	// PropKeywords is one value: the keywords as a JSON array of strings,
	// which Artifactory's keyword search matches with *"<keyword>"*.
	PropKeywords = "npm.keywords"
	// PropDistTag has one value per dist-tag. A tag names one version of
	// its package: a tarball that gains one takes it from the others.
	PropDistTag = "npm.disttag"
	// PropDeprecated is the version's deprecation message.
	PropDeprecated = "npm.deprecated"
	// PropLicenses is package.json's license, which 7.x writes beside the
	// npm.* properties when it indexes a tarball (RTFACT-30834). It is not
	// in npm's namespace: other tools, Xray among them, write it too.
	PropLicenses = "artifactory.licenses"
)

Properties the format keeps on an indexed tarball. Name, version, description, keywords and license follow from package.json and are set by the format; dist-tags and deprecation are the state npm changes after a publish, and the index follows them.

View Source
const (
	// KindReindex rebuilds a repository's index from its tarballs and
	// their properties: "Recalculating index for npm repository <repo>
	// scheduled to run" (JFrog's archived REST reference, KB 000005641).
	KindReindex = "npm.reindex"
	// KindConvert converts a repository to strict layout, moving each
	// tarball off its canonical path to it, as 7.x's conversion does in
	// the background (npm-repositories, "Enforce strict layout").
	KindConvert = "npm.convert"
)

The kinds of work the npm format runs from the persistent work queue (decisions 0033 and 0034), each keyed by repository key. Both are JFrog operations that 7.x schedules rather than runs before it answers.

View Source
const MaxVersionLength = 256

MaxVersionLength is the longest version string npm's semver parses.

View Source
const TagLatest = "latest"

TagLatest is the dist-tag npm installs when no version is asked for. 7.x stores it as it stores any dist-tag, as npm.disttag=latest on one tarball (7.84.10, RTDEV-37593 and RTDEV-40221; RTFACT-31340), so it moves only when one of decision 0034's rules moves it:

  1. npm.disttag=latest set on a tarball by any route makes its version latest (Annotated, through moveTags);
  2. a new version written without a dist-tag takes latest when it outranks the version that has it (claimLatest);
  3. a new version written with a dist-tag leaves latest where it is, unless no version has it yet (claimLatest; RTFACT-24072);
  4. a package left without latest, its version removed or the tag taken off, gives it to the version that outranks the others (settleLatest).

Which version outranks another is Settings.Outranks.

Variables

View Source
var ErrNotTarball = errors.New("npm: not a usable package tarball")

ErrNotTarball is content the format cannot index: no tar or tar.gz, no readable package.json in its top-level folder, a name npm would not accept, a version that is not SemVer, or more than limits allow. Such a .tgz is stored but not indexed (decision 0034, strict layout).

View Source
var ErrUnconverted = errors.New("npm: tarballs left off their canonical paths")

ErrUnconverted reports a conversion that left tarballs off their canonical paths.

Functions

func CanonicalPath

func CanonicalPath(name, version string) string

CanonicalPath is where a version's tarball is stored: the path npm names in its publish body and the JFrog CLI deploys to, so a scoped package's file name keeps its scope (@scope/name/-/@scope/name-1.0.0.tgz).

func CleanVersion

func CleanVersion(v string) (string, bool)

CleanVersion is npm's semver.clean: surrounding space and any leading "=" and "v" dropped, then a SemVer version without its build metadata, which npm ignores, so 1.0.0+build and 1.0.0 are one version. ok is false when v is no SemVer version.

func Keywords

func Keywords(raw json.RawMessage) []string

Keywords is a package.json keywords field as indexing reads it into npm.keywords: one string split at commas, and entries that are no non-empty string dropped. npm search matches against these, so a keyword found by the property search is found by npm search too.

func Outranks

func Outranks(a, b string) bool

Outranks reports whether version a outranks b for latest by default: a version that is no pre-release outranks every pre-release, and between two of the same kind the higher SemVer wins, as a 7.x local repository ranks them (RTFACT-30783, RTFACT-17732). Both are versions as the index cleans them, without build metadata, so a hyphen can only start a pre-release.

func Serves

func Serves(t repo.PackageType) bool

Serves reports whether t is a package type of this format.

func ValidName

func ValidName(name string) bool

ValidName reports whether npm accepts name for a package that exists, as validate-npm-package-name's validForOldPackages does: a name, or @scope/name, whose parts need no URL encoding, that starts with neither "." nor "_", and is not one npm reserves. Rules npm adds for new names, such as lower case, are left to the client, so older packages index.

Types

type Candidate

type Candidate struct {
	// Version is the index's cleaned version.
	Version string
	// Published is when its tarball was last deployed (Metadata.Published).
	Published time.Time
}

Candidate is a version as the latest rules weigh it.

type Dist

type Dist struct {
	// Shasum is the stored SHA-1, in hex.
	Shasum string `json:"shasum"`
	// Integrity is the stored SHA-512 in Subresource Integrity form.
	Integrity string `json:"integrity"`
}

Dist is a version's dist object, less the tarball URL, which a packument builds from the base URL of each request. 7.x's dist has nothing else (RTFACT-30472): npm's own registry adds fileCount and unpackedSize, which no JFrog client reads.

type Handler

type Handler struct {
	// The generic format's hooks for what npm leaves alone. Admit adds the
	// release and snapshot handling to its deploy policy (policy.go). A
	// republish's 403 belongs to the npm publish protocol: a REST deploy
	// over a tarball is an overwrite, which needs Delete, as for any item
	// (decision 0034).
	generic.Handler
	// Settings are the server's npm options.
	Settings Settings
}

Handler is the npm format.

func (Handler) Admit

func (h Handler) Admit(
	_ context.Context,
	env format.Env,
	c repo.Config,
	w format.Write,
) (format.Write, error)

Admit applies the deploy policy of every package type with the repository's release and snapshot handling between its checks, in Artifactory's order (RealRepoBase.assertValidPath): a blacked-out repository, then handleReleases and handleSnapshots, then the include and exclude patterns. 7.x refuses an npm local deploy the handling forbids with 409 (KB 000006800). The policy applies to every write that lands a file, an npm publish's included, as it does for Maven; a checksum upload is exempt, as Artifactory exempts checksum paths. Last, npm.enforce_path checks a deploy's file name (checkFileName).

func (Handler) Annotated

func (h Handler) Annotated(
	ctx context.Context,
	env format.Env,
	_ repo.Config,
	it types.Item,
	a format.Annotation,
) error

Annotated follows a change to an indexed tarball's dist-tags or deprecation, by whichever route it came: the npm protocol, the properties API, AQL, jf rt sp, or a deploy, copy, move or restore carrying them. A tag the tarball gains is taken from the package's other versions in the same transaction, so a tag names one version, latest included (rule 1). A change that leaves the package without latest settles it anew (rule 4), so npm dist-tag rm latest hands latest to the version that outranks the others, which may be the one it was taken from.

func (Handler) Deleted

func (h Handler) Deleted(
	ctx context.Context,
	env format.Env,
	c repo.Config,
	removed []types.Item,
) error

Deleted settles latest in each package a delete or a move took a tarball from (rule 4): pruning has dropped the versions left without a file, and with them, perhaps, the version that carried latest. The removed tarballs' versions are gone by now, so their packages are found by the names their paths give; a package with no version left is gone too, and a stray tarball's package keeps its latest.

func (Handler) Deployed

func (h Handler) Deployed(ctx context.Context, env format.Env, c repo.Config, it types.Item) error

Deployed indexes a tarball stored at its canonical path, and drops the version of a file that no longer is one, such as a tarball overwritten with another version's content. A tarball stored anywhere but where the index reads (pkgindex.Stored) is not indexed.

func (Handler) Inspect

func (h Handler) Inspect(
	ctx context.Context,
	env format.Env,
	c repo.Config,
	w format.Write,
) (any, error)

Inspect reads a tarball written at a path that could be canonical, or one npm.enforce_path checks, before the write's transaction. Other content needs no reading.

func (Handler) Owed

Owed is nothing: a read waits for no reindex or conversion, as 7.x's reads do not, since the deploys keep the index current.

func (Handler) Reindex

func (h Handler) Reindex(ctx context.Context, env format.Env, c repo.Config) error

Reindex rebuilds the repository's npm index from its tarballs and their properties, a remote repository's from its cache. Which repositories the JFrog reindex operation accepts is the API's rule, not the index's: decision 0034's local-only 400 is answered in internal/server.

func (Handler) Work

func (h Handler) Work(ctx context.Context, env format.Env, it types.WorkItem) error

Work runs a reindex or a conversion of the repository the item names. A repository that is gone, or no longer an npm one, owes nothing, and nor does an item of a kind the format no longer runs, which an earlier build may have left in the queue: running it as a reindex would rebuild a repository nobody asked about.

func (Handler) WorkKinds

func (Handler) WorkKinds() []string

WorkKinds are the kinds the npm format runs.

type Metadata

type Metadata struct {
	// Manifest is the tarball's package.json, compacted. Its version is as
	// the author wrote it; the index's version is the cleaned one.
	Manifest json.RawMessage `json:"manifest"`
	Dist     Dist            `json:"dist"`
	// HasInstallScript is Tarball.HasInstallScript.
	HasInstallScript bool `json:"has_install_script,omitempty"`
	// Tags are the dist-tags the tarball carries (npm.disttag), sorted.
	Tags []string `json:"tags,omitempty"`
	// Deprecated is the tarball's npm.deprecated message.
	Deprecated string `json:"deprecated,omitempty"`
	// Published is when the tarball was last deployed, in UTC to the
	// microsecond the stores keep.
	Published time.Time `json:"published"`
}

Metadata is a version's document in the package index (PackageVersion.Metadata, decision 0034): what packuments and search are built from, so a read needs neither the tarball nor its properties. Everything in it follows from the tarball, its stored checksums and its properties, so a reindex writes the same bytes.

func DecodeMetadata

func DecodeMetadata(b []byte) (Metadata, error)

DecodeMetadata reads a version's Metadata.

type Settings

type Settings struct {
	// TagLatestByPublish is npm.tag_latest_by_publish, 7.x's
	// artifactory.npm.tag.tagLatestByPublish: in rules 2 and 4 the version
	// deployed last outranks the others, pre-releases included, rather
	// than the highest. 7.x has it off by default (6.20's ConstantValues;
	// RTFACT-9754, RTFACT-20127).
	TagLatestByPublish bool
	// EnforcePath is npm.enforce_path, 7.x's artifactory.npm.enforce.path:
	// a package tarball deployed to a local repository under a file name
	// other than the one its package.json gives is refused (Admit). 7.x
	// has it off by default (npm-repositories).
	EnforcePath bool
}

Settings are the npm format's server-wide options (decision 0034), which reach it through formats.Settings. The zero value is 7.x's default.

func (Settings) Latest

func (s Settings) Latest(cs []Candidate) string

Latest is the version of cs that outranks every other, "" when cs is empty.

func (Settings) Outranks

func (s Settings) Outranks(a, b Candidate) bool

Outranks reports whether a outranks b for latest: by version (the package-level Outranks), or with TagLatestByPublish by deploy time, the later first. Two versions deployed at one moment fall back to the version order, so the choice never depends on the order they are read in. [I] How 7.x breaks that tie is unknown (#216).

type Tarball

type Tarball struct {
	// SHA256 is the content read, so a hook can tell the inspection of its
	// own write from one of other content.
	SHA256 string
	// Name is package.json's; Version is package.json's as CleanVersion
	// leaves it.
	Name, Version string
	// Manifest is package.json, compacted.
	Manifest json.RawMessage
	// Description and Keywords are package.json's, as npm normalises them:
	// a description that is no string is none, and keywords given as one
	// string are split at commas.
	Description string
	Keywords    []string
	// License is package.json's license when it is a string, an SPDX
	// expression such as "MIT" or "(MIT OR Apache-2.0)".
	License string
	// HasInstallScript is whether installing runs a script: a preinstall,
	// install or postinstall script, or a binding.gyp, for which npm runs
	// node-gyp rebuild unless gypfile is false.
	HasInstallScript bool
}

Tarball is what the format reads from a package tarball.

func ReadStored

func ReadStored(ctx context.Context, blobs format.Blobs, sha string) (*Tarball, bool, error)

ReadStored reads the stored content sha as a tarball; ok is false when it is none the format can index. The npm publish handler reads the tarball it uploaded with it, to check it against the body before storing it.

func ReadTarball

func ReadTarball(ra io.ReaderAt, size int64) (*Tarball, error)

ReadTarball reads the package tarball in ra, of size bytes, in one pass: package.json from its top-level folder, whatever that folder is called, and whether it has a binding.gyp. ErrNotTarball when the format cannot index it; any other error is a failure to read the content.

type WorkRequest

type WorkRequest struct {
	// By is recorded as the mover of what a conversion moves.
	By string `json:"by,omitempty"`
}

WorkRequest is the payload of the format's work: who asked for it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL