依赖选择器语法和查询

依赖选择器语法和查询

选择 CLI 版本:

描述

Description

npm query 命令公开了一个新的依赖选择器语法(参考并尊重 CSS 选择器 4 规范 的许多方面),其中:

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

  • 利用 CSS 中现有的已知语言语法和运算符来广泛访问不同的包信息

    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

  • 合并 npm 中类似查询命令的冗余逻辑(例如npm fund, npm ls, npm outdated, npm audit ...)

    Consolidates redundant logic of similar query commands in npm (ex. npm fund, npm ls, npm outdated, npm audit ...)

依赖选择器语法 v1.0.0

Dependency Selector Syntax v1.0.0

概述

Overview:

  • 没有 "type" 或 "tag" 选择器(例如div, h1, a) 作为依赖/目标是唯一可以查询的 Node 类型

    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

  • "dependencies" 一词是指在 Arborist 返回的 tree 中找到的任何 Node

    the term "dependencies" is in reference to any Node found in a tree returned by Arborist

组合器

Combinators

  • > 直系后代/子代

    > direct descendant/child

  • 任何后代/子级

    any descendant/child

  • ~ 兄弟姐妹

    ~ sibling

选择器

Selectors

  • * 万能选择器

    * universal selector

  • #<name> 依赖选择器(相当于 [name="..."]

    #<name> dependency selector (equivalent to [name="..."])

  • #<name>@<version>(相当于 [name=<name>]:semver(<version>)

    #<name>@<version> (equivalent to [name=<name>]:semver(<version>))

  • , 选择器列表分隔符

    , selector list delimiter

  • . 依赖类型选择器

    . dependency type selector

  • : 伪选择器

    : pseudo selector

依赖类型选择器

Dependency Type Selectors

  • package.jsondependencies 部分中找到的 .prod 依赖,或者是所述依赖的子项

    .prod dependency found in the dependencies section of package.json, or is a child of said dependency

  • package.jsondevDependencies 部分中找到的 .dev 依赖,或者是所述依赖的子项

    .dev dependency found in the devDependencies section of package.json, or is a child of said dependency

  • package.jsonoptionalDependencies 部分中找到 .optional 依赖,或者在 package.jsonpeerDependenciesMeta 部分的条目中设置了 "optional": true,或者所述依赖的子项

    .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

  • package.jsonpeerDependencies 部分中找到 .peer 依赖

    .peer dependency found in the peerDependencies section of package.json

  • package.jsonworkspaces 部分中找到 .workspace 依赖

    .workspace dependency found in the workspaces section of package.json

  • package.jsonbundleDependencies 部分中找到的 .bundled 依赖,或者是所述依赖的子项

    .bundled dependency found in the bundleDependencies section of package.json, or is a child of said dependency

伪选择器

Pseudo Selectors

  • :not(<selector>)

  • :has(<selector>)

  • :is(<selector list>)

  • :root 匹配根 node/依赖

    :root matches the root node/dependency

  • :scope 匹配它被查询的 node/依赖

    :scope matches node/dependency it was queried against

  • :empty 当一个依赖没有依赖时

    :empty when a dependency has no dependencies

  • :private 当一个依赖是私有的

    :private when a dependency is private

  • :link 当依赖被链接时(例如,工作区或手动包 linked

    :link when a dependency is linked (for instance, workspaces or packages manually linked

  • :deduped 当依赖已被数据去重时(注意这并不总是意味着依赖已被提升到 node_modules 的根目录)

    :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 当依赖被覆盖时

    :overridden when a dependency has been overridden

  • :extraneous 存在依赖但未定义为任何 node 的依赖时

    :extraneous when a dependency exists but is not defined as a dependency of any node

  • :invalid 当依赖版本超出其祖级指定范围时

    :invalid when a dependency version is out of its ancestors specified range

  • :missing 当在磁盘上找不到依赖时

    :missing when a dependency is not found on disk

  • :semver(<spec>, [selector], [function]) 将有效的 node-semver 版本或范围匹配到选择器

    :semver(<spec>, [selector], [function]) match a valid node-semver version or range to a selector

  • :path(<path>) glob 匹配基于相对于项目的依赖路径

    :path(<path>) glob matching based on dependencies path relative to the project

  • :type(<type>) 基于当前识别的类型

    :type(<type>) based on currently recognized types

  • :outdated(<type>) 当依赖过期时

    :outdated(<type>) when a dependency is outdated

:semver(<spec>, [selector], [function])

:semver() 伪选择器允许使用 semver 方法比较来自每个节点的 package.json 的字段。它最多接受 3 个参数,除第一个参数外,所有参数都是可选的。

The :semver() pseudo selector allows comparing fields from each node's package.json using semver methods. It accepts up to 3 parameters, all but the first of which are optional.

  • spec 一个 semver 版本或范围

    spec a semver version or range

  • selector 每个节点的属性选择器(默认 [version]

    selector an attribute selector for each node (default [version])

  • function 要应用的 semver 方法,其中之一:satisfiesintersectssubsetgtgtegtrltlteltreqneq 或特殊功能 infer(默认 infer

    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)

当使用特殊的 infer 函数时,将 spec 与来自节点的实际值进行比较。如果两者都是版本,则根据 semver.valid(),使用 eq。如果两个值都是范围,则根据 !semver.valid(),使用 intersects。如果值是混合类型,则使用 satisfies

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.

一些例子:

Some examples:

  • :semver(^1.0.0) 返回提供的范围 ^1.0.0 满足 version 的每个节点

    :semver(^1.0.0) returns every node that has a version satisfied by the provided range ^1.0.0

  • :semver(16.0.0, :attr(engines, [node])) 返回具有满足版本 16.0.0engines.node 属性的每个节点

    :semver(16.0.0, :attr(engines, [node])) returns every node which has an engines.node property satisfying the version 16.0.0

  • :semver(1.0.0, [version], lt) 每个 version 小于 1.0.0 的节点

    :semver(1.0.0, [version], lt) every node with a version less than 1.0.0

:outdated(<type>)

:outdated 伪选择器从注册表中检索数据并返回有关哪些依赖已过时的信息。类型参数可以是以下之一:

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:

  • any(默认)存在大于当前版本的版本

    any (default) a version exists that is greater than the current one

  • in-range 存在一个大于当前版本的版本,并且如果它的依赖至少满足一个版本

    in-range a version exists that is greater than the current one, and satisfies at least one if its dependents

  • out-of-range 存在大于当前版本的版本,但至少不满足其依赖之一

    out-of-range a version exists that is greater than the current one, does not satisfy at least one of its dependents

  • major 存在一个比当前版本大 semver major 的版本

    major a version exists that is a semver major greater than the current one

  • minor 存在的版本比当前版本小

    minor a version exists that is a semver minor greater than the current one

  • patch 存在一个比当前版本大的 semver 补丁的版本

    patch a version exists that is a semver patch greater than the current one

除了由伪选择器执行的过滤之外,还会将一些额外的数据添加到结果对象中。在每个节点的 queryContext 属性下可以找到以下数据。

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.

  • versions 给定节点的每个可用版本的数组

    versions an array of every available version of the given node

  • outdated.inRange 一个对象数组,每个对象都有一个 fromversions,其中 from 是依赖于当前节点的节点的磁盘位置,versions 是满足该依赖的所有可用版本的数组。仅当使用 :outdated(in-range) 时才会填充。

    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.

  • outdated.outOfRange 对象数组,形状与 inRange 相同,但 versions 数组是不满足依赖的每个可用版本。仅当使用 :outdated(out-of-range) 时才会填充。

    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.

一些例子:

Some examples:

  • :root > :outdated(major) 返回具有新 semver 主要版本的每个直接依赖

    :root > :outdated(major) returns every direct dependency that has a new semver major release

  • .prod:outdated(in-range) 返回具有满足其至少一个边缘的新版本的生产依赖

    .prod:outdated(in-range) returns production dependencies that have a new release that satisfies at least one of its edges in

属性选择器

Attribute Selectors

属性选择器评估 package.json 中的键/值对(如果它们是 String)。

The attribute selector evaluates the key/value pairs in package.json if they are Strings.

  • [] 属性选择器(即existence of attribute)

    [] attribute selector (ie. existence of attribute)

  • [attribute=value] 属性值是等价的...

    [attribute=value] attribute value is equivalant...

  • [attribute~=value] 属性值包含单词...

    [attribute~=value] attribute value contains word...

  • [attribute*=value] 属性值包含字符串...

    [attribute*=value] attribute value contains string...

  • [attribute|=value] 属性值等于或以...开头

    [attribute|=value] attribute value is equal to or starts with...

  • [attribute^=value] 属性值以...开头

    [attribute^=value] attribute value starts with...

  • [attribute$=value] 属性值以...结尾

    [attribute$=value] attribute value ends with...

Array & Object 属性选择器

Array & Object Attribute Selectors

通用的 :attr() 伪选择器标准化了一个模式,该模式可用于通过 ArboristNode.package 元数据访问 ObjectObjectArrayArrays 的属性选择。这允许在顶层 String 评估之外进行迭代属性选择。传递给 :attr() 的最后一个参数必须是 attribute 选择器或嵌套的 :attr()。请参阅以下示例:

The generic :attr() pseudo selector standardizes a pattern which can be used for attribute selection of Objects, Arrays or Arrays of Objects 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:

Objects

/* return dependencies that have a `scripts.test` containing `"tap"` */
*: attr(scripts, [test~=tap]);

嵌套 Objects

Nested Objects

嵌套对象表示为 :attr() 的顺序参数。

Nested objects are expressed as sequential arguments to :attr().

/* return dependencies that have a testling config for opera browsers */
*: attr(testling, browsers, [~=opera]);

Arrays

Array 专门使用特殊/保留的 . 字符代替典型的属性名称。将 String 传递给选择器时,Arrays 还支持精确的 value 匹配。

Arrays 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.

Array 属性选择示例:

Example of an Array Attribute Selection:

/* 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 示例:

Example of an Array matching directly to a value:

/* return dependencies that have the exact keyword "react" */
/* this is equivalent to `*:keywords([value="react"])` */
*: attr([keywords=react]);
Object 中的 Array 示例:

Example of an Array of Objects:

/* returns */
*: attr(contributors, [email=ruyadorno @github.com]);

Groups

依赖组由与其祖级的包关系定义(即package.json) 中定义的依赖类型。这种方法以用户为中心,因为生态系统已被教导首先考虑这些组中的依赖。依赖允许包含在多个组中(例如prod 依赖也可能是 dev 依赖(因为另一个 dev 依赖也需要它)并且也可能是 bundled - 该类型依赖的选择器如下所示:*.prod.dev.bundled).

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).

  • .prod

  • .dev

  • .optional

  • .peer

  • .bundled

  • .workspace

请注意,当前 workspace 依赖始终是 prod 依赖。此外,.root 依赖也被认为是 prod 依赖。

Please note that currently workspace deps are always prod dependencies. Additionally the .root dependency is also considered a prod dependency.

程序化用法

Programmatic Usage

  • ArboristNode 类有一个 .querySelectorAll() 方法

    Arborist's Node Class has a .querySelectorAll() method

    • 此方法将根据有效的查询选择器返回过滤的、扁平的依赖 Arborist Node 列表

      this method will return a filtered, flattened dependency Arborist Node list based on a valid query selector

const Arborist = require("@npmcli/arborist");
const arb = new Arborist({});
// root-level
arb.loadActual().then(async (tree) => {
// query all production dependencies
const results = await tree.querySelectorAll(".prod");
console.log(results);
});
// iterative
arb.loadActual().then(async (tree) => {
// query for the deduped version of react
const results = await tree.querySelectorAll("#react:not(:deduped)");
// query the deduped react for git deps
const deps = await results[0].querySelectorAll(":type(git)");
console.log(deps);
});

也可以看看

See Also

npm 中文网 - 粤ICP备13048890号