1--- 2title: Dependency Selector Syntax & Querying 3section: 7 4description: Dependency Selector Syntax & Querying 5--- 6 7### Description 8 9The [`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: 10 11- Standardizes the shape of, & querying of, dependency graphs with a robust object model, metadata & selector syntax 12- Leverages existing, known language syntax & operators from CSS to make disparate package information broadly accessible 13- Unlocks the ability to answer complex, multi-faceted questions about dependencies, their relationships & associative metadata 14- Consolidates redundant logic of similar query commands in `npm` (ex. `npm fund`, `npm ls`, `npm outdated`, `npm audit` ...) 15 16### Dependency Selector Syntax `v1.0.0` 17 18#### Overview: 19 20- 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 21- the term "dependencies" is in reference to any `Node` found in a `tree` returned by `Arborist` 22 23#### Combinators 24 25- `>` direct descendant/child 26- ` ` any descendant/child 27- `~` sibling 28 29#### Selectors 30 31- `*` universal selector 32- `#<name>` dependency selector (equivalent to `[name="..."]`) 33- `#<name>@<version>` (equivalent to `[name=<name>]:semver(<version>)`) 34- `,` selector list delimiter 35- `.` dependency type selector 36- `:` pseudo selector 37 38#### Dependency Type Selectors 39 40- `.prod` dependency found in the `dependencies` section of `package.json`, or is a child of said dependency 41- `.dev` dependency found in the `devDependencies` section of `package.json`, or is a child of said dependency 42- `.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 43- `.peer` dependency found in the `peerDependencies` section of `package.json` 44- `.workspace` dependency found in the [`workspaces`](https://docs.npmjs.com/cli/v8/using-npm/workspaces) section of `package.json` 45- `.bundled` dependency found in the `bundleDependencies` section of `package.json`, or is a child of said dependency 46 47#### Pseudo Selectors 48- [`:not(<selector>)`](https://developer.mozilla.org/en-US/docs/Web/CSS/:not) 49- [`:has(<selector>)`](https://developer.mozilla.org/en-US/docs/Web/CSS/:has) 50- [`:is(<selector list>)`](https://developer.mozilla.org/en-US/docs/Web/CSS/:is) 51- [`:root`](https://developer.mozilla.org/en-US/docs/Web/CSS/:root) matches the root node/dependency 52- [`:scope`](https://developer.mozilla.org/en-US/docs/Web/CSS/:scope) matches node/dependency it was queried against 53- [`:empty`](https://developer.mozilla.org/en-US/docs/Web/CSS/:empty) when a dependency has no dependencies 54- [`:private`](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#private) when a dependency is private 55- `:link` when a dependency is linked (for instance, workspaces or packages manually [`linked`](https://docs.npmjs.com/cli/v8/commands/npm-link) 56- `: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) 57- `:overridden` when a dependency has been overridden 58- `:extraneous` when a dependency exists but is not defined as a dependency of any node 59- `:invalid` when a dependency version is out of its ancestors specified range 60- `:missing` when a dependency is not found on disk 61- `:semver(<spec>, [selector], [function])` match a valid [`node-semver`](https://github.com/npm/node-semver) version or range to a selector 62- `:path(<path>)` [glob](https://www.npmjs.com/package/glob) matching based on dependencies path relative to the project 63- `:type(<type>)` [based on currently recognized types](https://github.com/npm/npm-package-arg#result-object) 64- `:outdated(<type>)` when a dependency is outdated 65 66##### `:semver(<spec>, [selector], [function])` 67 68The `: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. 69 70- `spec` a semver version or range 71- `selector` an attribute selector for each node (default `[version]`) 72- `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`) 73 74When 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. 75 76Some examples: 77 78- `:semver(^1.0.0)` returns every node that has a `version` satisfied by the provided range `^1.0.0` 79- `:semver(16.0.0, :attr(engines, [node]))` returns every node which has an `engines.node` property satisfying the version `16.0.0` 80- `:semver(1.0.0, [version], lt)` every node with a `version` less than `1.0.0` 81 82##### `:outdated(<type>)` 83 84The `: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: 85 86- `any` (default) a version exists that is greater than the current one 87- `in-range` a version exists that is greater than the current one, and satisfies at least one if its dependents 88- `out-of-range` a version exists that is greater than the current one, does not satisfy at least one of its dependents 89- `major` a version exists that is a semver major greater than the current one 90- `minor` a version exists that is a semver minor greater than the current one 91- `patch` a version exists that is a semver patch greater than the current one 92 93In 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. 94 95- `versions` an array of every available version of the given node 96- `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. 97- `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. 98 99Some examples: 100 101- `:root > :outdated(major)` returns every direct dependency that has a new semver major release 102- `.prod:outdated(in-range)` returns production dependencies that have a new release that satisfies at least one of its edges in 103 104#### [Attribute Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) 105 106The attribute selector evaluates the key/value pairs in `package.json` if they are `String`s. 107 108- `[]` attribute selector (ie. existence of attribute) 109- `[attribute=value]` attribute value is equivalant... 110- `[attribute~=value]` attribute value contains word... 111- `[attribute*=value]` attribute value contains string... 112- `[attribute|=value]` attribute value is equal to or starts with... 113- `[attribute^=value]` attribute value starts with... 114- `[attribute$=value]` attribute value ends with... 115 116#### `Array` & `Object` Attribute Selectors 117 118The 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: 119 120#### `Objects` 121 122```css 123/* return dependencies that have a `scripts.test` containing `"tap"` */ 124*:attr(scripts, [test~=tap]) 125``` 126 127#### Nested `Objects` 128 129Nested objects are expressed as sequential arguments to `:attr()`. 130 131```css 132/* return dependencies that have a testling config for opera browsers */ 133*:attr(testling, browsers, [~=opera]) 134``` 135 136#### `Arrays` 137 138`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. 139 140##### Example of an `Array` Attribute Selection: 141```css 142/* removes the distinction between properties & arrays */ 143/* ie. we'd have to check the property & iterate to match selection */ 144*:attr([keywords^=react]) 145*:attr(contributors, :attr([name~=Jordan])) 146``` 147 148##### Example of an `Array` matching directly to a value: 149```css 150/* return dependencies that have the exact keyword "react" */ 151/* this is equivalent to `*:keywords([value="react"])` */ 152*:attr([keywords=react]) 153``` 154 155##### Example of an `Array` of `Object`s: 156```css 157/* returns */ 158*:attr(contributors, [email=ruyadorno@github.com]) 159``` 160 161### Groups 162 163Dependency 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`). 164 165- `.prod` 166- `.dev` 167- `.optional` 168- `.peer` 169- `.bundled` 170- `.workspace` 171 172Please note that currently `workspace` deps are always `prod` dependencies. Additionally the `.root` dependency is also considered a `prod` dependency. 173 174### Programmatic Usage 175 176- `Arborist`'s `Node` Class has a `.querySelectorAll()` method 177 - this method will return a filtered, flattened dependency Arborist `Node` list based on a valid query selector 178 179```js 180const Arborist = require('@npmcli/arborist') 181const arb = new Arborist({}) 182``` 183 184```js 185// root-level 186arb.loadActual().then(async (tree) => { 187 // query all production dependencies 188 const results = await tree.querySelectorAll('.prod') 189 console.log(results) 190}) 191``` 192 193```js 194// iterative 195arb.loadActual().then(async (tree) => { 196 // query for the deduped version of react 197 const results = await tree.querySelectorAll('#react:not(:deduped)') 198 // query the deduped react for git deps 199 const deps = await results[0].querySelectorAll(':type(git)') 200 console.log(deps) 201}) 202``` 203 204## See Also 205 206* [npm query](/commands/npm-query) 207* [@npmcli/arborist](https://npm.im/@npmcli/arborist) 208