From c5bf4b3091b296f8cc7e810cfbf14e6864982a5b Mon Sep 17 00:00:00 2001
From: Emily Marigold Klassen <760204+forivall@users.noreply.github.com>
Date: Wed, 17 Apr 2024 11:17:14 -0700
Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#69373=20[@npmcli/a?=
=?UTF-8?q?rborist]=20Add=20inventory=20query=20types=20by=20@forivall?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
types/npmcli__arborist/index.d.ts | 44 +++++++++++++--
.../npmcli__arborist-tests.ts | 54 ++++++++++++++++++-
types/npmcli__arborist/package.json | 1 +
3 files changed, 93 insertions(+), 6 deletions(-)
diff --git a/types/npmcli__arborist/index.d.ts b/types/npmcli__arborist/index.d.ts
index c5468a3ca599e1..b708e02aa46981 100644
--- a/types/npmcli__arborist/index.d.ts
+++ b/types/npmcli__arborist/index.d.ts
@@ -1,3 +1,5 @@
+///
+
import { LockDependency, PackageLock as _PackageLock } from "@npm/types";
import { PackageJson } from "@npmcli/package-json";
import { EventEmitter } from "events";
@@ -217,9 +219,14 @@ declare namespace Arborist {
/** Errors encountered while parsing package.json or version specifiers. */
errors: Error[];
- /** If this is a Link, this is the node it */
+ /** If this is a Link, this is the node it links to */
target: Node;
+ overridden?: boolean;
+
+ /** When overrides are used, this is the virtual root */
+ sourceReference?: Node;
+
/** Identify the node that will be returned when code in this package runs `require(name)` */
resolve(name: string): Node;
@@ -228,12 +235,16 @@ declare namespace Arborist {
querySelectorAll(query: string): Promise;
toJSON(): Node;
+
+ explain(seen?: Node[]): Explanation;
}
class Link extends Node {
isLink: true;
}
+ type DependencyProblem = "DETACHED" | "MISSING" | "PEER LOCAL" | "INVALID";
+
/**
* Edge objects represent a dependency relationship a package node to the
* point in the tree where the dependency will be loaded. As nodes are
@@ -262,6 +273,8 @@ declare namespace Arborist {
to: Node;
/** True if `edge.to` satisfies the specifier. */
valid: boolean;
+ invalid: boolean;
+ missing: boolean;
/**
* A string indicating the type of error if there is a problem, or `null`
* if it's valid. Values, in order of precedence:
@@ -276,8 +289,10 @@ declare namespace Arborist {
* means that the dependency is not a peer.
* * `INVALID` Indicates that the dependency does not satisfy `edge.spec`.
*/
- error: "DETACHED" | "MISSING" | "PEER LOCAL" | "INVALID" | null;
+ error: DependencyProblem | null;
reload(hard?: boolean): void;
+
+ explain(seen?: Node[]): Explanation;
}
interface AuditReport extends Map {
@@ -400,8 +415,8 @@ declare namespace Arborist {
filter(fn: (node: Node) => boolean): Generator;
add(node: Node): void;
delete(node: Node): void;
- query(key: string, val: Node): Set;
- query(key: string, val?: never): Set;
+ query(key: string, val: string | undefined): Set;
+ query(key: string): IterableIterator;
has(node: Node): boolean;
set?(k: never, v: never): never;
}
@@ -430,6 +445,27 @@ declare namespace Arborist {
stdout: string;
stderr: string;
}
+ interface DependencyExplanation {
+ type: string | null;
+ name: string;
+ spec: string;
+ rawSpec?: string;
+ overridden?: boolean;
+ bundled?: boolean;
+ error?: DependencyProblem;
+ from?: Node;
+ }
+ interface Explanation {
+ name: string;
+ version: string;
+ errors?: Error[];
+ package?: PackageJson;
+ whileInstalling?: { name: string; version: string; path: string };
+ location?: string;
+ isWorkspace?: boolean;
+ dependents?: DependencyExplanation[];
+ linksIn?: DependencyExplanation[];
+ }
}
export = Arborist;
diff --git a/types/npmcli__arborist/npmcli__arborist-tests.ts b/types/npmcli__arborist/npmcli__arborist-tests.ts
index f373b1eeb2b109..67326b763d8353 100644
--- a/types/npmcli__arborist/npmcli__arborist-tests.ts
+++ b/types/npmcli__arborist/npmcli__arborist-tests.ts
@@ -36,7 +36,7 @@ arb.reify({
arb.loadActual().then(async tree => {
// query all production dependencies
const results = await tree.querySelectorAll(".prod");
- console.log(results);
+ results; // $ExpectType Node[]
});
// iterative
@@ -45,5 +45,55 @@ arb.loadActual().then(async tree => {
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);
+ deps; // $ExpectType Node[]
});
+
+async function why(spec: string) {
+ const tree = await arb.loadActual();
+ const nodesSet = tree.inventory.query("packageName", spec);
+ const nodes: Arborist.Node[] = [];
+ nodesSet.forEach((node) => {
+ nodes.push(node);
+ });
+
+ const expls = [];
+ for (const node of nodes) {
+ const { extraneous, dev, optional, devOptional, peer, inBundle, overridden } = node;
+ const explRaw = node.explain();
+ const expl = explRaw as
+ & typeof explRaw
+ & (
+ | {
+ extraneous: true;
+ dev?: never;
+ optional?: never;
+ devOptional?: never;
+ peer?: never;
+ bundled?: never;
+ overridden?: never;
+ }
+ | {
+ extraneous?: false;
+ dev: boolean;
+ optional: boolean;
+ devOptional: boolean;
+ peer: boolean;
+ bundled: boolean;
+ overridden: boolean;
+ }
+ );
+ if (extraneous) {
+ expl.extraneous = true;
+ } else {
+ expl.dev = dev;
+ expl.optional = optional;
+ expl.devOptional = devOptional;
+ expl.peer = peer;
+ expl.bundled = inBundle;
+ expl.overridden = overridden;
+ }
+ expls.push(expl);
+ }
+ return expls;
+}
+why("lodash");
diff --git a/types/npmcli__arborist/package.json b/types/npmcli__arborist/package.json
index 99058ab8751a5a..7d032c9a7ef41a 100644
--- a/types/npmcli__arborist/package.json
+++ b/types/npmcli__arborist/package.json
@@ -8,6 +8,7 @@
"dependencies": {
"@npm/types": "*",
"@types/cacache": "*",
+ "@types/node": "*",
"@types/npmcli__package-json": "*",
"@types/pacote": "*"
},