Movatterモバイル変換


[0]ホーム

URL:


Skip to searchSkip to content

Site navigation

Dependency Selector Syntax & Querying

Dependency Selector Syntax & Querying

Select CLI Version:

Description

Thenpm query command exposes a new dependency selector syntax (informed by & respecting many aspects of theCSS Selectors 4 Spec) which:

  • Standardizes the shape of, & querying of, dependency graphs with a robust object model, metadata & selector syntax
  • Leverages existing, known language syntax & operators from CSS to make disparate package information broadly accessible
  • Unlocks the ability to answer complex, multi-faceted questions about dependencies, their relationships & associative metadata
  • Consolidates redundant logic of similar query commands innpm (ex.npm fund,npm ls,npm outdated,npm audit ...)

Dependency Selector Syntax

Overview:

  • there is no "type" or "tag" selectors (ex.div, h1, a) as a dependency/target is the only type ofNode that can be queried
  • the term "dependencies" is in reference to anyNode found in atree returned byArborist

Combinators

  • > direct descendant/child
  • any descendant/child
  • ~ sibling

Selectors

  • * universal selector
  • #<name> dependency selector (equivalent to[name="..."])
  • #<name>@<version> (equivalent to[name=<name>]:semver(<version>))
  • , selector list delimiter
  • . dependency type selector
  • : pseudo selector

Dependency Type Selectors

  • .prod dependency found in thedependencies section ofpackage.json, or is a child of said dependency
  • .dev dependency found in thedevDependencies section ofpackage.json, or is a child of said dependency
  • .optional dependency found in theoptionalDependencies section ofpackage.json, or has"optional": true set in its entry in thepeerDependenciesMeta section ofpackage.json, or a child of said dependency
  • .peer dependency found in thepeerDependencies section ofpackage.json
  • .workspace dependency found in theworkspaces section ofpackage.json
  • .bundled dependency found in thebundleDependencies section ofpackage.json, or is a child of said dependency

Pseudo Selectors

  • :not(<selector>)
  • :has(<selector>)
  • :is(<selector list>)
  • :root matches the root node/dependency
  • :scope matches node/dependency it was queried against
  • :empty when a dependency has no dependencies
  • :private when a dependency is private
  • :link when a dependency is linked (for instance, workspaces or packages manuallylinked
  • :deduped when a dependency has been deduped (note that this doesnot always mean the dependency has been hoisted to the root of node_modules)
  • :overridden when a dependency has been overridden
  • :extraneous when a dependency exists but is not defined as a dependency of any node
  • :invalid when a dependency version is out of its ancestors specified range
  • :missing when a dependency is not found on disk
  • :semver(<spec>, [selector], [function]) match a validnode-semver version or range to a selector
  • :path(<path>)glob matching based on dependencies path relative to the project
  • :type(<type>)based on currently recognized types
  • :outdated(<type>) when a dependency is outdated
  • :vuln(<selector>) when a dependency has a known vulnerability

:semver(<spec>, [selector], [function])

The:semver() pseudo selector allows comparing fields from each node'spackage.json usingsemver methods. It accepts up to 3 parameters, all but the first of which are optional.

  • spec a semver version or range
  • selector an attribute selector for each node (default[version])
  • function a semver method to apply, one of:satisfies,intersects,subset,gt,gte,gtr,lt,lte,ltr,eq,neq or the special functioninfer (defaultinfer)

When the specialinfer function is used thespec and the actual value from the node are compared. If both are versions, according tosemver.valid(),eq is used. If both values are ranges, according to!semver.valid(),intersects is used. If the values are mixed typessatisfies is used.

Some examples:

  • :semver(^1.0.0) returns every node that has aversion satisfied by the provided range^1.0.0
  • :semver(16.0.0, :attr(engines, [node])) returns every node which has anengines.node property satisfying the version16.0.0
  • :semver(1.0.0, [version], lt) every node with aversion less than1.0.0

:outdated(<type>)

The:outdated pseudo selector retrieves data from the registry and returns information about which of your dependencies are outdated. The type parameter may be one of the following:

  • any (default) a version exists that is greater than the current one
  • in-range a version exists that is greater than the current one, and satisfies at least one if its parent's dependencies
  • out-of-range a version exists that is greater than the current one, does not satisfy at least one of its parent's dependencies
  • major a version exists that is a semver major greater than the current one
  • minor a version exists that is a semver minor greater than the current one
  • patch a version exists that is a semver patch greater than the current one

In addition to the filtering performed by the pseudo selector, some extra data is added to the resulting objects. The following data can be found under thequeryContext property of each node.

  • versions an array of every available version of the given node
  • outdated.inRange an array of objects, each with afrom andversions, wherefrom is the on-disk location of the node that depends on the current node andversions is an array of all available versions that satisfies that dependency. This is only populated if:outdated(in-range) is used.
  • outdated.outOfRange an array of objects, identical in shape toinRange, but where theversions array is every available version that does not satisfy the dependency. This is only populated if:outdated(out-of-range) is used.

Some examples:

  • :root > :outdated(major) returns every direct dependency that has a new semver major release
  • .prod:outdated(in-range) returns production dependencies that have a new release that satisfies at least one of its parent's dependencies

:vuln

The:vuln pseudo selector retrieves data from the registry and returns information about which if your dependencies has a known vulnerability. Only dependencies whose current version matches a vulnerability will be returned. For example if you havesemver@7.6.0 in your tree, a vulnerability forsemver which affects versions<=6.3.1 will not match.

You can also filter results by certain attributes in advisories. Currently that includesseverity andcwe. Note that severity filtering is done per severity, it does not include severities "higher" or "lower" than the one specified.

In addition to the filtering performed by the pseudo selector, info about each relevant advisory will be added to thequeryContext attribute of each node under theadvisories attribute.

Some examples:

  • :root > .prod:vuln returns direct production dependencies with any known vulnerability
  • :vuln([severity=high]) returns only dependencies with a vulnerability with ahigh severity.
  • :vuln([severity=high],[severity=moderate]) returns only dependencies with a vulnerability with ahigh ormoderate severity.
  • :vuln([cwe=1333]) returns only dependencies with a vulnerability that includes CWE-1333 (ReDoS)

Attribute Selectors

The attribute selector evaluates the key/value pairs inpackage.json if they areStrings.

  • [] attribute selector (ie. existence of attribute)
  • [attribute=value] attribute value is equivalent...
  • [attribute~=value] attribute value contains word...
  • [attribute*=value] attribute value contains string...
  • [attribute|=value] attribute value is equal to or starts with...
  • [attribute^=value] attribute value starts with...
  • [attribute$=value] attribute value ends with...

Array &Object Attribute Selectors

The generic:attr() pseudo selector standardizes a pattern which can be used for attribute selection ofObjects,Arrays orArrays ofObjects accessible viaArborist'sNode.package metadata. This allows for iterative attribute selection beyond top-levelString evaluation. The last argument passed to:attr() must be anattribute selector or a nested:attr(). See examples below:

Objects

/* return dependencies that have a `scripts.test` containing `"tap"` */
*:attr(scripts, [test~=tap]);

NestedObjects

Nested objects are expressed as sequential arguments to:attr().

/* return dependencies that have a testling config for opera browsers */
*:attr(testling, browsers, [~=opera]);

Arrays

Arrays specifically uses a special/reserved. character in place of a typical attribute name.Arrays also support exactvalue matching when aString is passed to the selector.

Example of anArray Attribute Selection:

/* removes the distinction between properties & arrays */
/* ie. we'd have to check the property & iterate to match selection */
*:attr([keywords^=react])
*:attr(contributors,:attr([name~=Jordan]))

Example of anArray matching directly to a value:

/* return dependencies that have the exact keyword "react" */
/* this is equivalent to `*:keywords([value="react"])` */
*:attr([keywords=react]);

Example of anArray ofObjects:

/* returns */
*:attr(contributors, [email=ruyadorno@github.com]);

Groups

Dependency groups are defined by the package relationships to their ancestors (ie. the dependency types that are defined inpackage.json). This approach is user-centric as the ecosystem has been taught to think about dependencies in these groups first-and-foremost. Dependencies are allowed to be included in multiple groups (ex. aprod dependency may also be adev dependency (in that it's also required by anotherdev dependency) & may also bebundled - a selector for that type of dependency would look like:*.prod.dev.bundled).

  • .prod
  • .dev
  • .optional
  • .peer
  • .bundled
  • .workspace

Please note that currentlyworkspace deps are alwaysprod dependencies. Additionally the.root dependency is also considered aprod dependency.

Programmatic Usage

  • Arborist'sNode Class has a.querySelectorAll() method
    • this method will return a filtered, flattened dependency ArboristNode list based on a valid query selector
constArborist=require("@npmcli/arborist");
const arb=newArborist({});
// root-level
arb.loadActual().then(async(tree)=>{
// query all production dependencies
const results=await tree.querySelectorAll(".prod");
console.log(results);
});
// iterative
arb.loadActual().then(async(tree)=>{
// query for the deduped version of react
const results=await tree.querySelectorAll("#react:not(:deduped)");
// query the deduped react for git deps
const deps=await results[0].querySelectorAll(":type(git)");
console.log(deps);
});

See Also

Edit this page on GitHub
4 contributorswraithgarGoodDaisybitdawlukekarrys
Last edited bywraithgar onFebruary 6, 2024

[8]ページ先頭

©2009-2025 Movatter.jp