npm query
is a new top-level command as of npm v8.16.0 which accepts a Dependency Selector (as defined in the Dependency Selector Syntax Specification) & returns a filtered JSON Array/NodeList of dependencies from your project. We believe this capability has been a missing piece of the package management ecosystem; With its introduction we hope to unlock the potential for developers to self-serve in asking new, complex questions about their dependencies, their relationships & associative metadata.
For many JavaScript developers, the Dependency Selector Syntax will look very familiar as it is actually an adapted form of CSS. We leveraged this existing, known language & its operators to make disparate package information broadly accessible.
Example Uses:
If I wanted to list all of my dependencies (similar to npm list --all
) I can run:
npm query "*"
If I wanted to find every version of react
& lodash
in my project I can run:
npm query "#react, #lodash"
If I wanted to find all react
versions not-defined as a peer dependency I can run:
npm query "#react:not(.peer)"
If I wanted to find all the dependencies in my project that used an MIT
license I'd change that query to be:
npm query "[license=MIT]"
If I wanted to find all the git dependencies in my project I can run:
npm query ":type(git)"
If I wanted to find out which of my transitive dependencies used a postinstall
script I could run:
npm query ":attr(scripts, [postinstall]):not(:root > *)"
Programmatic Usage
We know many developers in the ecosystem will also want to leverage this new syntax themselves, so we've built it right into the programmatic brain of the CLI. Under the hood, we’ve added a new .querySelectorAll()
method to the existing Node
Class we use in the @npmcli/arborist
library. Tooling authors can now load up & query their dependencies just like we do.
// index.js
const Arborist = require('@npmcli/arborist')
const arb = new Arborist({})
arb.loadActual((tree) => {
// query all workspaces
const results = await tree.querySelectorAll('.workspace')
console.log(results)
})
You can learn more about the syntax & usage in our documentation here: https://docs.npmjs.org/cli/v8/using-npm/dependency-selectors
What's next?
Looking ahead we’ve got work planned to add new pseudo states & selectors based on registry metadata that should unlock another host of capabilities aimed at auditing (examples include: :outdated
:deprecated
:vulnerable
:cve()
& :cwe()
). As documented in the original RFC proposal we will also consider supporting a query
flag or reading from stdin
to existing commands.