Skip to content

The :attr() pseudo-class selects packages based on nested properties of their package.json metadata. While attribute selectors match top-level fields, :attr() lets you drill into nested objects.

Syntax

:attr(key, [attr=value])
:attr(key, nestedKey, [attr=value])

Arguments are a path of property keys, ending with a standard attribute selector.

Examples

Optional peer dependencies

Select packages that declare foo as an optional peer dependency:

Terminal
$ vlt query ':attr(peerDependenciesMeta, foo, [optional=true])'

This is equivalent to checking:

{
"peerDependenciesMeta": {
"foo": {
"optional": true
}
}
}

Engine requirements

Select packages that have a node engine requirement:

Terminal
$ vlt query ':attr(engines, [node])'

Scripts

Select packages that have a build script:

Terminal
$ vlt query ':attr(scripts, [build])'

Select packages that have a test script using vitest:

Terminal
$ vlt query ':attr(scripts, [test*=vitest])'

What gets selected

Given this dependency graph:

my-app
├── react@18.2.0
│ └── loose-envify@1.4.0 ← has scripts.postinstall
├── typescript@5.3.0 ← has engines.node
└── vite@5.0.0 ← has engines.node

The query :attr(engines, [node]) selects:

my-app
├── react@18.2.0
│ └── loose-envify@1.4.0
├── typescript@5.3.0 ✅ has engines.node
└── vite@5.0.0 ✅ has engines.node

Combining with combinators

Find direct dependencies that have a build script:

Terminal
$ vlt query ':project > :attr(scripts, [build])'

See also