11cb0ef41Sopenharmony_ci--- 21cb0ef41Sopenharmony_cititle: Dependency Selector Syntax & Querying 31cb0ef41Sopenharmony_cisection: 7 41cb0ef41Sopenharmony_cidescription: Dependency Selector Syntax & Querying 51cb0ef41Sopenharmony_ci--- 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci### Description 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciThe [`npm query`](/commands/npm-query) command exposes a new dependency selector syntax (informed by & respecting many aspects of the [CSS Selectors 4 Spec](https://dev.w3.org/csswg/selectors4/#relational)) which: 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci- Standardizes the shape of, & querying of, dependency graphs with a robust object model, metadata & selector syntax 121cb0ef41Sopenharmony_ci- Leverages existing, known language syntax & operators from CSS to make disparate package information broadly accessible 131cb0ef41Sopenharmony_ci- Unlocks the ability to answer complex, multi-faceted questions about dependencies, their relationships & associative metadata 141cb0ef41Sopenharmony_ci- Consolidates redundant logic of similar query commands in `npm` (ex. `npm fund`, `npm ls`, `npm outdated`, `npm audit` ...) 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci### Dependency Selector Syntax 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci#### Overview: 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ci- there is no "type" or "tag" selectors (ex. `div, h1, a`) as a dependency/target is the only type of `Node` that can be queried 211cb0ef41Sopenharmony_ci- the term "dependencies" is in reference to any `Node` found in a `tree` returned by `Arborist` 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci#### Combinators 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci- `>` direct descendant/child 261cb0ef41Sopenharmony_ci- ` ` any descendant/child 271cb0ef41Sopenharmony_ci- `~` sibling 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci#### Selectors 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci- `*` universal selector 321cb0ef41Sopenharmony_ci- `#<name>` dependency selector (equivalent to `[name="..."]`) 331cb0ef41Sopenharmony_ci- `#<name>@<version>` (equivalent to `[name=<name>]:semver(<version>)`) 341cb0ef41Sopenharmony_ci- `,` selector list delimiter 351cb0ef41Sopenharmony_ci- `.` dependency type selector 361cb0ef41Sopenharmony_ci- `:` pseudo selector 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci#### Dependency Type Selectors 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci- `.prod` dependency found in the `dependencies` section of `package.json`, or is a child of said dependency 411cb0ef41Sopenharmony_ci- `.dev` dependency found in the `devDependencies` section of `package.json`, or is a child of said dependency 421cb0ef41Sopenharmony_ci- `.optional` dependency found in the `optionalDependencies` section of `package.json`, or has `"optional": true` set in its entry in the `peerDependenciesMeta` section of `package.json`, or a child of said dependency 431cb0ef41Sopenharmony_ci- `.peer` dependency found in the `peerDependencies` section of `package.json` 441cb0ef41Sopenharmony_ci- `.workspace` dependency found in the [`workspaces`](https://docs.npmjs.com/cli/v8/using-npm/workspaces) section of `package.json` 451cb0ef41Sopenharmony_ci- `.bundled` dependency found in the `bundleDependencies` section of `package.json`, or is a child of said dependency 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci#### Pseudo Selectors 481cb0ef41Sopenharmony_ci- [`:not(<selector>)`](https://developer.mozilla.org/en-US/docs/Web/CSS/:not) 491cb0ef41Sopenharmony_ci- [`:has(<selector>)`](https://developer.mozilla.org/en-US/docs/Web/CSS/:has) 501cb0ef41Sopenharmony_ci- [`:is(<selector list>)`](https://developer.mozilla.org/en-US/docs/Web/CSS/:is) 511cb0ef41Sopenharmony_ci- [`:root`](https://developer.mozilla.org/en-US/docs/Web/CSS/:root) matches the root node/dependency 521cb0ef41Sopenharmony_ci- [`:scope`](https://developer.mozilla.org/en-US/docs/Web/CSS/:scope) matches node/dependency it was queried against 531cb0ef41Sopenharmony_ci- [`:empty`](https://developer.mozilla.org/en-US/docs/Web/CSS/:empty) when a dependency has no dependencies 541cb0ef41Sopenharmony_ci- [`:private`](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#private) when a dependency is private 551cb0ef41Sopenharmony_ci- `:link` when a dependency is linked (for instance, workspaces or packages manually [`linked`](https://docs.npmjs.com/cli/v8/commands/npm-link) 561cb0ef41Sopenharmony_ci- `:deduped` when a dependency has been deduped (note that this does *not* always mean the dependency has been hoisted to the root of node_modules) 571cb0ef41Sopenharmony_ci- `:overridden` when a dependency has been overridden 581cb0ef41Sopenharmony_ci- `:extraneous` when a dependency exists but is not defined as a dependency of any node 591cb0ef41Sopenharmony_ci- `:invalid` when a dependency version is out of its ancestors specified range 601cb0ef41Sopenharmony_ci- `:missing` when a dependency is not found on disk 611cb0ef41Sopenharmony_ci- `:semver(<spec>, [selector], [function])` match a valid [`node-semver`](https://github.com/npm/node-semver) version or range to a selector 621cb0ef41Sopenharmony_ci- `:path(<path>)` [glob](https://www.npmjs.com/package/glob) matching based on dependencies path relative to the project 631cb0ef41Sopenharmony_ci- `:type(<type>)` [based on currently recognized types](https://github.com/npm/npm-package-arg#result-object) 641cb0ef41Sopenharmony_ci- `:outdated(<type>)` when a dependency is outdated 651cb0ef41Sopenharmony_ci- `:vuln(<selector>)` when a dependency has a known vulnerability 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci##### `:semver(<spec>, [selector], [function])` 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ciThe `:semver()` pseudo selector allows comparing fields from each node's `package.json` using [semver](https://github.com/npm/node-semver#readme) methods. It accepts up to 3 parameters, all but the first of which are optional. 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci- `spec` a semver version or range 721cb0ef41Sopenharmony_ci- `selector` an attribute selector for each node (default `[version]`) 731cb0ef41Sopenharmony_ci- `function` a semver method to apply, one of: `satisfies`, `intersects`, `subset`, `gt`, `gte`, `gtr`, `lt`, `lte`, `ltr`, `eq`, `neq` or the special function `infer` (default `infer`) 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ciWhen the special `infer` function is used the `spec` and the actual value from the node are compared. If both are versions, according to `semver.valid()`, `eq` is used. If both values are ranges, according to `!semver.valid()`, `intersects` is used. If the values are mixed types `satisfies` is used. 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ciSome examples: 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci- `:semver(^1.0.0)` returns every node that has a `version` satisfied by the provided range `^1.0.0` 801cb0ef41Sopenharmony_ci- `:semver(16.0.0, :attr(engines, [node]))` returns every node which has an `engines.node` property satisfying the version `16.0.0` 811cb0ef41Sopenharmony_ci- `:semver(1.0.0, [version], lt)` every node with a `version` less than `1.0.0` 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci##### `:outdated(<type>)` 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ciThe `: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: 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci- `any` (default) a version exists that is greater than the current one 881cb0ef41Sopenharmony_ci- `in-range` a version exists that is greater than the current one, and satisfies at least one if its parent's dependencies 891cb0ef41Sopenharmony_ci- `out-of-range` a version exists that is greater than the current one, does not satisfy at least one of its parent's dependencies 901cb0ef41Sopenharmony_ci- `major` a version exists that is a semver major greater than the current one 911cb0ef41Sopenharmony_ci- `minor` a version exists that is a semver minor greater than the current one 921cb0ef41Sopenharmony_ci- `patch` a version exists that is a semver patch greater than the current one 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ciIn 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 the `queryContext` property of each node. 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci- `versions` an array of every available version of the given node 971cb0ef41Sopenharmony_ci- `outdated.inRange` an array of objects, each with a `from` and `versions`, where `from` is the on-disk location of the node that depends on the current node and `versions` is an array of all available versions that satisfies that dependency. This is only populated if `:outdated(in-range)` is used. 981cb0ef41Sopenharmony_ci- `outdated.outOfRange` an array of objects, identical in shape to `inRange`, but where the `versions` array is every available version that does not satisfy the dependency. This is only populated if `:outdated(out-of-range)` is used. 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ciSome examples: 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci- `:root > :outdated(major)` returns every direct dependency that has a new semver major release 1031cb0ef41Sopenharmony_ci- `.prod:outdated(in-range)` returns production dependencies that have a new release that satisfies at least one of its parent's dependencies 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci##### `:vuln` 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ciThe `: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 have `semver@7.6.0` in your tree, a vulnerability for `semver` which affects versions `<=6.3.1` will not match. 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ciYou can also filter results by certain attributes in advisories. Currently that includes `severity` and `cwe`. Note that severity filtering is done per severity, it does not include severities "higher" or "lower" than the one specified. 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ciIn addition to the filtering performed by the pseudo selector, info about each relevant advisory will be added to the `queryContext` attribute of each node under the `advisories` attribute. 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ciSome examples: 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci- `:root > .prod:vuln` returns direct production dependencies with any known vulnerability 1161cb0ef41Sopenharmony_ci- `:vuln([severity=high])` returns only dependencies with a vulnerability with a `high` severity. 1171cb0ef41Sopenharmony_ci- `:vuln([severity=high],[severity=moderate])` returns only dependencies with a vulnerability with a `high` or `moderate` severity. 1181cb0ef41Sopenharmony_ci- `:vuln([cwe=1333])` returns only dependencies with a vulnerability that includes CWE-1333 (ReDoS) 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci#### [Attribute Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ciThe attribute selector evaluates the key/value pairs in `package.json` if they are `String`s. 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci- `[]` attribute selector (ie. existence of attribute) 1251cb0ef41Sopenharmony_ci- `[attribute=value]` attribute value is equivalent... 1261cb0ef41Sopenharmony_ci- `[attribute~=value]` attribute value contains word... 1271cb0ef41Sopenharmony_ci- `[attribute*=value]` attribute value contains string... 1281cb0ef41Sopenharmony_ci- `[attribute|=value]` attribute value is equal to or starts with... 1291cb0ef41Sopenharmony_ci- `[attribute^=value]` attribute value starts with... 1301cb0ef41Sopenharmony_ci- `[attribute$=value]` attribute value ends with... 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci#### `Array` & `Object` Attribute Selectors 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ciThe generic `:attr()` pseudo selector standardizes a pattern which can be used for attribute selection of `Object`s, `Array`s or `Arrays` of `Object`s accessible via `Arborist`'s `Node.package` metadata. This allows for iterative attribute selection beyond top-level `String` evaluation. The last argument passed to `:attr()` must be an `attribute` selector or a nested `:attr()`. See examples below: 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci#### `Objects` 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci```css 1391cb0ef41Sopenharmony_ci/* return dependencies that have a `scripts.test` containing `"tap"` */ 1401cb0ef41Sopenharmony_ci*:attr(scripts, [test~=tap]) 1411cb0ef41Sopenharmony_ci``` 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci#### Nested `Objects` 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ciNested objects are expressed as sequential arguments to `:attr()`. 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci```css 1481cb0ef41Sopenharmony_ci/* return dependencies that have a testling config for opera browsers */ 1491cb0ef41Sopenharmony_ci*:attr(testling, browsers, [~=opera]) 1501cb0ef41Sopenharmony_ci``` 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci#### `Arrays` 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci`Array`s specifically uses a special/reserved `.` character in place of a typical attribute name. `Arrays` also support exact `value` matching when a `String` is passed to the selector. 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci##### Example of an `Array` Attribute Selection: 1571cb0ef41Sopenharmony_ci```css 1581cb0ef41Sopenharmony_ci/* removes the distinction between properties & arrays */ 1591cb0ef41Sopenharmony_ci/* ie. we'd have to check the property & iterate to match selection */ 1601cb0ef41Sopenharmony_ci*:attr([keywords^=react]) 1611cb0ef41Sopenharmony_ci*:attr(contributors, :attr([name~=Jordan])) 1621cb0ef41Sopenharmony_ci``` 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci##### Example of an `Array` matching directly to a value: 1651cb0ef41Sopenharmony_ci```css 1661cb0ef41Sopenharmony_ci/* return dependencies that have the exact keyword "react" */ 1671cb0ef41Sopenharmony_ci/* this is equivalent to `*:keywords([value="react"])` */ 1681cb0ef41Sopenharmony_ci*:attr([keywords=react]) 1691cb0ef41Sopenharmony_ci``` 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci##### Example of an `Array` of `Object`s: 1721cb0ef41Sopenharmony_ci```css 1731cb0ef41Sopenharmony_ci/* returns */ 1741cb0ef41Sopenharmony_ci*:attr(contributors, [email=ruyadorno@github.com]) 1751cb0ef41Sopenharmony_ci``` 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci### Groups 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ciDependency groups are defined by the package relationships to their ancestors (ie. the dependency types that are defined in `package.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. a `prod` dependency may also be a `dev` dependency (in that it's also required by another `dev` dependency) & may also be `bundled` - a selector for that type of dependency would look like: `*.prod.dev.bundled`). 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci- `.prod` 1821cb0ef41Sopenharmony_ci- `.dev` 1831cb0ef41Sopenharmony_ci- `.optional` 1841cb0ef41Sopenharmony_ci- `.peer` 1851cb0ef41Sopenharmony_ci- `.bundled` 1861cb0ef41Sopenharmony_ci- `.workspace` 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ciPlease note that currently `workspace` deps are always `prod` dependencies. Additionally the `.root` dependency is also considered a `prod` dependency. 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci### Programmatic Usage 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci- `Arborist`'s `Node` Class has a `.querySelectorAll()` method 1931cb0ef41Sopenharmony_ci - this method will return a filtered, flattened dependency Arborist `Node` list based on a valid query selector 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci```js 1961cb0ef41Sopenharmony_ciconst Arborist = require('@npmcli/arborist') 1971cb0ef41Sopenharmony_ciconst arb = new Arborist({}) 1981cb0ef41Sopenharmony_ci``` 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci```js 2011cb0ef41Sopenharmony_ci// root-level 2021cb0ef41Sopenharmony_ciarb.loadActual().then(async (tree) => { 2031cb0ef41Sopenharmony_ci // query all production dependencies 2041cb0ef41Sopenharmony_ci const results = await tree.querySelectorAll('.prod') 2051cb0ef41Sopenharmony_ci console.log(results) 2061cb0ef41Sopenharmony_ci}) 2071cb0ef41Sopenharmony_ci``` 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci```js 2101cb0ef41Sopenharmony_ci// iterative 2111cb0ef41Sopenharmony_ciarb.loadActual().then(async (tree) => { 2121cb0ef41Sopenharmony_ci // query for the deduped version of react 2131cb0ef41Sopenharmony_ci const results = await tree.querySelectorAll('#react:not(:deduped)') 2141cb0ef41Sopenharmony_ci // query the deduped react for git deps 2151cb0ef41Sopenharmony_ci const deps = await results[0].querySelectorAll(':type(git)') 2161cb0ef41Sopenharmony_ci console.log(deps) 2171cb0ef41Sopenharmony_ci}) 2181cb0ef41Sopenharmony_ci``` 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci## See Also 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci* [npm query](/commands/npm-query) 2231cb0ef41Sopenharmony_ci* [@npmcli/arborist](https://npm.im/@npmcli/arborist) 224