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