Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
dependency-selectors.md248 linesDownload Raw Back to using-npm
1---
2title: Dependency Selectors
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.
15`npm fund`, `npm ls`, `npm outdated`, `npm audit` ...)
16
17### Dependency Selector Syntax
18
19#### Overview:
20
21- there is no "type" or "tag" selectors (ex.
22`div, h1, a`) as a dependency/target is the only type of `Node` that can be queried
23- the term "dependencies" is in reference to any `Node` found in a `tree` returned by `Arborist`
24
25#### Combinators
26
27- `>` direct descendant/child
28- ` ` any descendant/child
29- `~` sibling
30
31#### Selectors
32
33- `*` universal selector
34- `#<name>` dependency selector (equivalent to `[name="..."]`)
35- `#<name>@<version>` (equivalent to `[name=<name>]:semver(<version>)`)
36- `,` selector list delimiter
37- `.` dependency type selector
38- `:` pseudo selector
39
40#### Dependency Type Selectors
41
42- `.prod` dependency found in the `dependencies` section of `package.json`, or is a child of said dependency
43- `.dev` dependency found in the `devDependencies` section of `package.json`, or is a child of said dependency
44- `.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
45- `.peer` dependency found in the `peerDependencies` section of `package.json`
46- `.workspace` dependency found in the [`workspaces`](https://docs.npmjs.com/cli/v8/using-npm/workspaces) section of `package.json`
47- `.bundled` dependency found in the `bundleDependencies` section of `package.json`, or is a child of said dependency
48
49#### Pseudo Selectors
50- [`:not(<selector>)`](https://developer.mozilla.org/en-US/docs/Web/CSS/:not)
51- [`:has(<selector>)`](https://developer.mozilla.org/en-US/docs/Web/CSS/:has)
52- [`:is(<selector list>)`](https://developer.mozilla.org/en-US/docs/Web/CSS/:is)
53- [`:root`](https://developer.mozilla.org/en-US/docs/Web/CSS/:root) matches the root node/dependency
54- [`:scope`](https://developer.mozilla.org/en-US/docs/Web/CSS/:scope) matches node/dependency it was queried against
55- [`:empty`](https://developer.mozilla.org/en-US/docs/Web/CSS/:empty) when a dependency has no dependencies
56- [`:private`](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#private) when a dependency is private
57- `:link` when a dependency is linked (for instance, workspaces or packages manually [`linked`](https://docs.npmjs.com/cli/v8/commands/npm-link)
58- `: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)
59- `:overridden` when a dependency has been overridden
60- `:extraneous` when a dependency exists but is not defined as a dependency of any node
61- `:invalid` when a dependency version is out of its ancestors specified range
62- `:missing` when a dependency is not found on disk
63- `:semver(<spec>, [selector], [function])` match a valid [`node-semver`](https://github.com/npm/node-semver) version or range to a selector
64- `:path(<path>)` [glob](https://www.npmjs.com/package/glob) matching based on dependencies path relative to the project
65- `:type(<type>)` [based on currently recognized types](https://github.com/npm/npm-package-arg#result-object).  You can also use the aggregate type of `registry` for any registry dependency (e.g. tag, version, range, alias)
66- `:outdated(<type>)` when a dependency is outdated
67- `:vuln(<selector>)` when a dependency has a known vulnerability
68
69##### `:semver(<spec>, [selector], [function])`
70
71The `:semver()` pseudo selector allows comparing fields from each node's `package.json` using [semver](https://github.com/npm/node-semver#readme) methods.
72It accepts up to 3 parameters, all but the first of which are optional.
73
74- `spec` a semver version or range
75- `selector` an attribute selector for each node (default `[version]`)
76- `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`)
77
78When the special `infer` function is used the `spec` and the actual value from the node are compared.
79If both are versions, according to `semver.valid()`, `eq` is used.
80If both values are ranges, according to `!semver.valid()`, `intersects` is used.
81If the values are mixed types `satisfies` is used.
82
83Some examples:
84
85- `:semver(^1.0.0)` returns every node that has a `version` satisfied by the provided range `^1.0.0`
86- `:semver(16.0.0, :attr(engines, [node]))` returns every node which has an `engines.node` property satisfying the version `16.0.0`
87- `:semver(1.0.0, [version], lt)` every node with a `version` less than `1.0.0`
88
89##### `:outdated(<type>)`
90
91The `:outdated` pseudo selector retrieves data from the registry and returns information about which of your dependencies are outdated.
92The type parameter may be one of the following:
93
94- `any` (default) a version exists that is greater than the current one
95- `in-range` a version exists that is greater than the current one, and satisfies at least one if its parent's dependencies
96- `out-of-range` a version exists that is greater than the current one, does not satisfy at least one of its parent's dependencies
97- `major` a version exists that is a semver major greater than the current one
98- `minor` a version exists that is a semver minor greater than the current one
99- `patch` a version exists that is a semver patch greater than the current one
100
101In addition to the filtering performed by the pseudo selector, some extra data is added to the resulting objects.
102The following data can be found under the `queryContext` property of each node.
103
104- `versions` an array of every available version of the given node
105- `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.
106This is only populated if `:outdated(in-range)` is used.
107- `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.
108This is only populated if `:outdated(out-of-range)` is used.
109
110Some examples:
111
112- `:root > :outdated(major)` returns every direct dependency that has a new semver major release
113- `.prod:outdated(in-range)` returns production dependencies that have a new release that satisfies at least one of its parent's dependencies
114
115##### `:vuln`
116
117The `:vuln` pseudo selector retrieves data from the registry and returns information about which if your dependencies has a known vulnerability.
118Only dependencies whose current version matches a vulnerability will be returned.
119For example if you have `semver@7.6.0` in your tree, a vulnerability for `semver` which affects versions `<=6.3.1` will not match.
120
121You can also filter results by certain attributes in advisories.
122Currently that includes `severity` and `cwe`.
123Note that severity filtering is done per severity, it does not include severities "higher" or "lower" than the one specified.
124
125In 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.
126
127Some examples:
128
129- `:root > .prod:vuln` returns direct production dependencies with any known vulnerability
130- `:vuln([severity=high])` returns only dependencies with a vulnerability with a `high` severity.
131- `:vuln([severity=high],[severity=moderate])` returns only dependencies with a vulnerability with a `high`  or `moderate` severity.
132- `:vuln([cwe=1333])` returns only dependencies with a vulnerability that includes CWE-1333 (ReDoS)
133
134#### [Attribute Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors)
135
136The attribute selector evaluates the key/value pairs in `package.json` if they are `String`s.
137
138- `[]` attribute selector (ie.
139existence of attribute)
140- `[attribute=value]` attribute value is equivalent...
141- `[attribute~=value]` attribute value contains word...
142- `[attribute*=value]` attribute value contains string...
143- `[attribute|=value]` attribute value is equal to or starts with...
144- `[attribute^=value]` attribute value starts with...
145- `[attribute$=value]` attribute value ends with...
146
147#### `Array` & `Object` Attribute Selectors
148
149The 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.
150This allows for iterative attribute selection beyond top-level `String` evaluation.
151The last argument passed to `:attr()` must be an `attribute` selector or a nested `:attr()`.
152See examples below:
153
154#### `Objects`
155
156```css
157/* return dependencies that have a `scripts.test` containing `"tap"` */
158*:attr(scripts, [test~=tap])
159```
160
161#### Nested `Objects`
162
163Nested objects are expressed as sequential arguments to `:attr()`.
164
165```css
166/* return dependencies that have a [testling config](https://ci.testling.com/guide/advanced_configuration) for opera browsers */
167*:attr(testling, browsers, [~=opera])
168```
169
170#### `Arrays`
171
172`Array`s specifically uses a special/reserved `.` character in place of a typical attribute name.
173`Arrays` also support exact `value` matching when a `String` is passed to the selector.
174
175##### Example of an `Array` Attribute Selection:
176```css
177/* removes the distinction between properties & arrays */
178/* ie. we'd have to check the property & iterate to match selection */
179*:attr([keywords^=react])
180*:attr(contributors, :attr([name~=Jordan]))
181```
182
183##### Example of an `Array` matching directly to a value:
184```css
185/* return dependencies that have the exact keyword "react" */
186/* this is equivalent to `*:keywords([value="react"])` */
187*:attr([keywords=react])
188```
189
190##### Example of an `Array` of `Object`s:
191```css
192/* returns */
193*:attr(contributors, [email=ruyadorno@github.com])
194```
195
196### Groups
197
198Dependency groups are defined by the package relationships to their ancestors (ie.
199the dependency types that are defined in `package.json`).
200This approach is user-centric as the ecosystem has been taught to think about dependencies in these groups first-and-foremost.
201Dependencies are allowed to be included in multiple groups (ex.
202a `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`).
203
204- `.prod`
205- `.dev`
206- `.optional`
207- `.peer`
208- `.bundled`
209- `.workspace`
210
211Please note that currently `workspace` deps are always `prod` dependencies.
212Additionally the `.root` dependency is also considered a `prod` dependency.
213
214### Programmatic Usage
215
216- `Arborist`'s `Node` Class has a `.querySelectorAll()` method
217  - this method will return a filtered, flattened dependency Arborist `Node` list based on a valid query selector
218
219```js
220const Arborist = require('@npmcli/arborist')
221const arb = new Arborist({})
222```
223
224```js
225// root-level
226arb.loadActual().then(async (tree) => {
227  // query all production dependencies
228  const results = await tree.querySelectorAll('.prod')
229  console.log(results)
230})
231```
232
233```js
234// iterative
235arb.loadActual().then(async (tree) => {
236  // query for the deduped version of react
237  const results = await tree.querySelectorAll('#react:not(:deduped)')
238  // query the deduped react for git deps
239  const deps = await results[0].querySelectorAll(':type(git)')
240  console.log(deps)
241})
242```
243
244## See Also
245
246* [npm query](/commands/npm-query)
247* [@npmcli/arborist](https://npm.im/@npmcli/arborist)
248 
codekingpro/portable-devtools · Team Ai