目录
依赖项选择器语法和查询
选择 CLI 版本
目录
描述
The npm query
command exposes a new dependency selector syntax (informed by & respecting many aspects of the CSS Selectors 4 Spec) which
- Standardizes the shape of, & querying of, dependency graphs with a robust object model, metadata & selector syntax
- Leverages existing, known language syntax & operators from CSS to make disparate package information broadly accessible
- Unlocks the ability to answer complex, multi-faceted questions about dependencies, their relationships & associative metadata
- Consolidates redundant logic of similar query commands in
npm
(ex.npm fund
,npm ls
,npm outdated
,npm audit
...)
依赖项选择器语法
概述
- there is no "type" or "tag" selectors (ex.
div, h1, a
) as a dependency/target is the only type ofNode
that can be queried - the term "dependencies" is in reference to any
Node
found in atree
returned byArborist
组合器
>
direct descendant/childany descendant/child
~
sibling
选择器
*
universal selector#<name>
dependency selector (equivalent to[name="..."]
)#<name>@<version>
(equivalent to[name=<name>]:semver(<version>)
),
selector list delimiter.
dependency type selector:
pseudo selector
依赖项类型选择器
.prod
dependency found in thedependencies
section ofpackage.json
, or is a child of said dependency.dev
dependency found in thedevDependencies
section ofpackage.json
, or is a child of said dependency.optional
dependency found in theoptionalDependencies
section ofpackage.json
, or has"optional": true
set in its entry in thepeerDependenciesMeta
section ofpackage.json
, or a child of said dependency.peer
dependency found in thepeerDependencies
section ofpackage.json
.workspace
dependency found in theworkspaces
section ofpackage.json
.bundled
dependency found in thebundleDependencies
section ofpackage.json
, or is a child of said dependency
伪选择器
:not(<selector>)
:has(<selector>)
:is(<selector list>)
:root
matches the root node/dependency:scope
matches node/dependency it was queried against:empty
when a dependency has no dependencies:private
when a dependency is private:link
when a dependency is linked (for instance, workspaces or packages manuallylinked
: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):overridden
when a dependency has been overridden:extraneous
when a dependency exists but is not defined as a dependency of any node:invalid
when a dependency version is out of its ancestors specified range:missing
when a dependency is not found on disk:semver(<spec>, [selector], [function])
匹配有效node-semver
版本或范围到选择器:path(<path>)
glob 匹配基于相对于项目的依赖路径:type(<type>)
基于当前识别的类型:outdated(<type>)
当依赖项过时时:vuln(<selector>)
当依赖项存在已知漏洞时
:semver(<spec>, [selector], [function])
The :semver()
伪选择器允许使用 semver 方法比较每个节点的 package.json
中的字段。它最多接受 3 个参数,除了第一个参数之外都是可选的。
spec
一个 semver 版本或范围selector
每个节点的属性选择器(默认[version]
)function
要应用的 semver 方法,以下之一:satisfies
,intersects
,subset
,gt
,gte
,gtr
,lt
,lte
,ltr
,eq
,neq
或特殊函数infer
(默认infer
)
当使用特殊函数 infer
时,会比较 spec
和来自节点的实际值。如果两者都是版本,根据 semver.valid()
,将使用 eq
。如果两个值都是范围,根据 !semver.valid()
,将使用 intersects
。如果值是混合类型,将使用 satisfies
。
一些示例
:semver(^1.0.0)
返回每个version
满足提供的范围^1.0.0
的节点:semver(16.0.0, :attr(engines, [node]))
返回每个engines.node
属性满足版本16.0.0
的节点:semver(1.0.0, [version], lt)
每个version
小于1.0.0
的节点
:outdated(<type>)
The :outdated
伪选择器从注册表检索数据,并返回有关哪些依赖项过时的信息。类型参数可以是以下之一
any
(默认)存在一个版本大于当前版本in-range
存在一个版本大于当前版本,并且至少满足其父级的依赖项之一out-of-range
存在一个版本大于当前版本,不满足其父级的依赖项之一major
存在一个版本是 semver 主版本大于当前版本minor
存在一个版本是 semver 次版本大于当前版本patch
存在一个版本是 semver 修补程序版本大于当前版本
除了伪选择器执行的过滤之外,还会向结果对象添加一些额外的信息。以下数据可以在每个节点的 queryContext
属性下找到。
versions
给定节点的所有可用版本的数组outdated.inRange
对象数组,每个对象都有一个from
和versions
,其中from
是依赖于当前节点的节点的磁盘位置,而versions
是满足该依赖项的所有可用版本的数组。仅当使用:outdated(in-range)
时才会填充此信息。outdated.outOfRange
对象数组,形状与inRange
相同,但versions
数组是所有不满足依赖项的可用版本。仅当使用:outdated(out-of-range)
时才会填充此信息。
一些示例
:root > :outdated(major)
返回每个具有新 semver 主版本的直接依赖项.prod:outdated(in-range)
返回具有满足其父级依赖项之一的新版本的生产依赖项
:vuln
The :vuln
伪选择器从注册表检索数据,并返回有关您的依赖项中是否存在已知漏洞的信息。仅当依赖项的当前版本与漏洞匹配时,才会返回依赖项。例如,如果您在树中具有 [email protected]
,则针对 semver
影响版本 <=6.3.1
的漏洞将不会匹配。
您还可以按咨询中的某些属性过滤结果。目前这包括 severity
和 cwe
。请注意,严重性过滤是按严重性执行的,不包括指定严重性“更高”或“更低”的严重性。
除了伪选择器执行的过滤之外,有关每个相关咨询的信息将添加到每个节点的 queryContext
属性下的 advisories
属性中。
一些示例
:root > .prod:vuln
返回具有任何已知漏洞的直接生产依赖项:vuln([severity=high])
仅返回具有high
严重性的漏洞的依赖项。:vuln([severity=high],[severity=moderate])
仅返回具有high
或moderate
严重性的漏洞的依赖项。:vuln([cwe=1333])
仅返回包含 CWE-1333(ReDoS)的漏洞的依赖项
属性选择器
属性选择器评估 package.json
中的键值对,如果它们是 String
。
[]
属性选择器(即属性的存在)[attribute=value]
属性值等效于...[attribute~=value]
属性值包含单词...[attribute*=value]
属性值包含字符串...[attribute|=value]
属性值等于或以...开头[attribute^=value]
属性值以...开头[attribute$=value]
属性值以...结尾
Array
& Object
属性选择器
通用 :attr()
伪选择器标准化了一种模式,该模式可用于 Object
、Array
或 Array
的 Object
属性选择,这些属性可以通过 Arborist
的 Node.package
元数据访问。这允许进行迭代属性选择,超出顶层 String
评估。传递给 :attr()
的最后一个参数必须是 attribute
选择器或嵌套的 :attr()
。请参阅下面的示例
对象
/* return dependencies that have a `scripts.test` containing `"tap"` */*: attr(scripts, [test~=tap]);
嵌套的 Objects
嵌套对象表示为 :attr()
的顺序参数。
/* return dependencies that have a testling config for opera browsers */*: attr(testling, browsers, [~=opera]);
数组
Array
特别是在典型属性名称的位置使用特殊的/保留的 .
字符。 Array
还支持当将 String
传递给选择器时,进行精确的 value
匹配。
Array
属性选择示例
/* removes the distinction between properties & arrays *//* ie. we'd have to check the property & iterate to match selection */*:attr([keywords^=react])*:attr(contributors, :attr([name~=Jordan]))
Array
直接匹配值的示例
/* return dependencies that have the exact keyword "react" *//* this is equivalent to `*:keywords([value="react"])` */*: attr([keywords=react]);
Array
的 Object
示例
/* returns */*: attr(contributors, [email=ruyadorno @github.com]);
组
依赖项组由包与其祖先的关系定义(即在 package.json
中定义的依赖项类型)。这种方法以用户为中心,因为生态系统已经被教导首先从这些组中思考依赖项。依赖项被允许包含在多个组中(例如,prod
依赖项也可能是 dev
依赖项(因为它也被另一个 dev
依赖项需要)并且也可能是 bundled
- 针对这种类型依赖项的选择器将如下所示:*.prod.dev.bundled
)。
.prod
.dev
.optional
.peer
.bundled
.workspace
请注意,目前 workspace
依赖项始终是 prod
依赖项。此外,.root
依赖项也被视为 prod
依赖项。
编程方式使用
Arborist
的Node
类具有.querySelectorAll()
方法- 该方法将根据有效的查询选择器返回过滤后的扁平化依赖项 Arborist
Node
列表
- 该方法将根据有效的查询选择器返回过滤后的扁平化依赖项 Arborist
const Arborist = require("@npmcli/arborist");const arb = new Arborist({});
// root-levelarb.loadActual().then(async (tree) => {// query all production dependenciesconst results = await tree.querySelectorAll(".prod");console.log(results);});
// iterativearb.loadActual().then(async (tree) => {// query for the deduped version of reactconst results = await tree.querySelectorAll("#react:not(:deduped)");// query the deduped react for git depsconst deps = await results[0].querySelectorAll(":type(git)");console.log(deps);});