相依性選擇器語法和查詢

相依性選擇器語法和查詢

選擇 CLI 版本

說明

npm query 指令公開了新的相依性選擇器語法(根據 CSS 選擇器 4 規範 的許多面向提供資訊並予以尊重),其中

  • 透過強健的物件模型、元資料和選擇器語法,標準化相依性圖形的形狀和查詢
  • 利用現有的已知語言語法和 CSS 的運算子,讓不同的套件資訊廣泛地被存取
  • 解鎖回答關於相依性、其關係和關聯元資料的複雜且多面向問題的能力
  • 整合 npm 中類似查詢指令的重複邏輯(例如 npm fundnpm lsnpm outdatednpm audit ...)

相依性選擇器語法

概觀

  • 沒有「類型」或「標籤」選取器(例如 div, h1, a),因為相依關係/目標是唯一可以查詢的 Node 類型
  • 「相依關係」一詞是指 Arborist 傳回的 tree 中找到的任何 Node

組合器

  • > 直接後代/子項
  • 任何後代/子項
  • ~ 同層

選擇器

  • * 萬用選取器
  • #<name> 相依關係選取器(等同於 [name="..."]
  • #<name>@<version>(等同於 [name=<name>]:semver(<version>)
  • , 選取器清單分隔符號
  • . 相依關係類型選取器
  • : 偽選取器

相依性類型選擇器

  • .prodpackage.jsondependencies 區段中找到的相依關係,或為該相依關係的子項
  • .devpackage.jsondevDependencies 區段中找到的相依關係,或為該相依關係的子項
  • .optionalpackage.jsonoptionalDependencies 區段中找到的相依關係,或在 package.jsonpeerDependenciesMeta 區段中其項目設定 "optional": true,或為該相依關係的子項
  • .peerpackage.jsonpeerDependencies 區段中找到的相依關係
  • .workspacepackage.jsonworkspaces 區段中找到的相依關係
  • .bundledpackage.jsonbundleDependencies 區段中找到的相依關係,或為該相依關係的子項

偽選擇器

  • :not(<selector>)
  • :has(<selector>)
  • :is(<selector list>)
  • :root 符合根節點/依賴項
  • :scope 符合針對其執行查詢的節點/依賴項
  • :empty 當依賴項沒有任何依賴項時
  • :private 當依賴項為私有時
  • :link 當依賴項已連結(例如,工作區或手動連結的套件 linked
  • :deduped 當依賴項已重複刪除(請注意,這並不總是表示依賴項已被提升至 node_modules 的根目錄)
  • :overridden 當依賴項已被覆寫時
  • :extraneous 當依賴項存在,但未定義為任何節點的依賴項時
  • :invalid 當依賴項版本超出其祖先指定的範圍時
  • :missing 當在磁碟上找不到依賴項時
  • :semver(<spec>, [selector], [function]) 將有效的 node-semver 版本或範圍符合選取器
  • :path(<path>) glob 根據依賴項相對於專案的路徑進行比對
  • :type(<type>) 根據目前識别的類型
  • :outdated(<type>) 當依賴項已過時時
  • :vuln(<selector>) 當依賴項具有已知的漏洞時
:semver(<spec>, [selector], [function])

偽選取器 :semver() 允許使用 semver 方法,比較每個節點的 package.json 中的欄位。它最多接受 3 個參數,除了第一個參數之外,其餘都是選用的。

  • spec semver 版本或範圍
  • selector 針對每個節點的屬性選取器(預設 [version]
  • function 要套用的 semver 方法,其中之一:satisfiesintersectssubsetgtgtegtrltlteltreqneq 或特殊函式 infer(預設 infer

當使用特殊函式 infer 時,會比較 spec 和節點中的實際值。如果兩者都是版本,根據 semver.valid(),會使用 eq。如果兩個值都是範圍,根據 !semver.valid(),會使用 intersects。如果值是混合類型,會使用 satisfies

一些範例

  • :semver(^1.0.0) 會傳回每個具有版本 ^1.0.0 範圍所滿足的 version 的節點
  • :semver(16.0.0, :attr(engines, [node])) 會傳回每個具有滿足版本 16.0.0engines.node 屬性的節點
  • :semver(1.0.0, [version], lt) 每個具有小於 1.0.0version 的節點
:outdated(<type>)

偽選取器 :outdated 會從註冊中心擷取資料,並傳回關於哪些依賴項已過期的資訊。類型參數可以是下列其中之一

  • any(預設)存在大於目前版本
  • in-range 存在大於目前版本,且滿足至少一個其父系依賴項的版本
  • out-of-range 存在大於目前版本,且不滿足至少一個其父系依賴項的版本
  • major 有個版本存在,其 semver major 大於目前的版本
  • minor 有個版本存在,其 semver minor 大於目前的版本
  • patch 有個版本存在,其 semver patch 大於目前的版本

除了偽選取器執行的過濾之外,還會將一些額外資料新增到結果物件。下列資料可以在每個節點的 queryContext 屬性中找到。

  • versions 給定節點的每個可用版本的陣列
  • outdated.inRange 物件陣列,每個物件都有 fromversions,其中 from 是依賴於目前節點的節點的磁碟位置,而 versions 是滿足該相依性的所有可用版本的陣列。這只有在使用 :outdated(in-range) 時才會填充。
  • outdated.outOfRange 物件陣列,其形狀與 inRange 相同,但 versions 陣列是不滿足相依性的每個可用版本。這只有在使用 :outdated(out-of-range) 時才會填充。

一些範例

  • :root > :outdated(major) 傳回每個具有新的 semver major 版本的直接相依性
  • .prod:outdated(in-range) 傳回具有新版本的生產相依性,該新版本滿足其父項相依性的其中一個以上
:vuln

:vuln 偽選取器會從註冊表中擷取資料,並傳回有關您的相依性是否有已知弱點的資訊。只有其目前版本符合弱點的相依性才會傳回。例如,如果您的樹狀結構中有 semver@7.6.0,則會影響版本 <=6.3.1semver 弱點將不會符合。

您也可以根據建議中的特定屬性來過濾結果。目前包括 severitycwe。請注意,嚴重性過濾是針對每個嚴重性進行,它不包含比指定的嚴重性「更高」或「更低」的嚴重性。

除了偽選取器執行的過濾之外,每個相關建議的資訊會新增到每個節點的 queryContext 屬性,位於 advisories 屬性之下。

一些範例

  • :root > .prod:vuln 傳回具有任何已知弱點的直接生產相依性
  • :vuln([severity=high]) 僅傳回具有嚴重性為 high 的漏洞之相依性。
  • :vuln([severity=high],[severity=moderate]) 僅傳回具有嚴重性為 highmoderate 的漏洞之相依性。
  • :vuln([cwe=1333]) 僅傳回具有包含 CWE-1333 (ReDoS) 的漏洞之相依性。

屬性選擇器

屬性選擇器會評估 package.json 中的鍵/值配對,如果它們是 String

  • [] 屬性選擇器(即屬性存在)
  • [attribute=value] 屬性值等於...
  • [attribute~=value] 屬性值包含字詞...
  • [attribute*=value] 屬性值包含字串...
  • [attribute|=value] 屬性值等於或開頭為...
  • [attribute^=value] 屬性值開頭為...
  • [attribute$=value] 屬性值結尾為...

ArrayObject 屬性選擇器

通用 :attr() 偽選擇器標準化一種模式,可用於選擇 ObjectArrayObjectArray,這些可透過 ArboristNode.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 特別使用特殊/保留的 . 字元來取代典型的屬性名稱。當 String 傳遞給選擇器時,Array 也支援精確 value 比對。

範例:陣列屬性選取
/* 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]))
範例:陣列直接比對值
/* return dependencies that have the exact keyword "react" */
/* this is equivalent to `*:keywords([value="react"])` */
*: attr([keywords=react]);
範例:陣列物件
/* 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相依性。

程式化使用

  • ArboristNode類別有一個.querySelectorAll()方法
    • 此方法會根據有效的查詢選取器,傳回經過篩選、扁平化的相依性ArboristNode清單
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);
});

另請參閱