···8383 }
8484 });
85858686- it('does not mark shared deps as peer when reachable both ways', async () => {
8787- // if a package is reachable through both regular and peer deps,
8888- // it should NOT be marked as peer
8686+ it('marks direct peer deps as peer even when also a transitive dep', async () => {
8787+ // if a package is a direct peer dep of root but also reachable through
8888+ // a transitive non-peer path, it should still be marked as peer
8989 const result = await resolve(['is-odd@3.0.1']);
90909191 // pretend is-number is also a peer dep (but it's already a regular dep)
9292 const peerDepNames = new Set(['is-number']);
9393 const packages = buildInstalledPackages(result.roots[0], peerDepNames);
94949595- // is-number should still be marked as peer because it's only through peer edge
9595+ // is-number should be marked as peer because it's a direct peer dep of root
9696 const isNumber = packages.find((p) => p.name === 'is-number')!;
9797 expect(isNumber.isPeer).toBe(true);
9898+ });
9999+100100+ it('marks peer deps as peer when also reachable through transitive deps', async () => {
101101+ // graphql-request has graphql as a peer dep
102102+ // @graphql-typed-document-node/core (a regular dep) also depends on graphql
103103+ // graphql should still be marked as peer since it's a direct peer dep of root
104104+ const result = await resolve(['graphql-request@7.4.0']);
105105+ const peerDepNames = new Set(['graphql']);
106106+ const packages = buildInstalledPackages(result.roots[0], peerDepNames);
107107+108108+ // graphql should be marked as peer
109109+ const graphql = packages.find((p) => p.name === 'graphql');
110110+ expect(graphql).toBeDefined();
111111+ expect(graphql!.isPeer).toBe(true);
112112+113113+ // @graphql-typed-document-node/core should NOT be marked as peer
114114+ const typedDocNode = packages.find((p) => p.name === '@graphql-typed-document-node/core');
115115+ expect(typedDocNode).toBeDefined();
116116+ expect(typedDocNode!.isPeer).toBe(false);
98117 });
99118});
+7-1
src/npm/lib/installed-packages.ts
···101101 // build final array
102102 const packages: InstalledPackage[] = [];
103103 for (const [key, { pkg, level, dependents, dependencies }] of packageMap) {
104104+ // a package is a peer if:
105105+ // 1. it's a direct peer dependency of the root, OR
106106+ // 2. it's only reachable through peer dependency subtrees
107107+ const isDirectPeerOfRoot = peerDepNames.has(pkg.name);
108108+ const isOnlyReachableThroughPeers = !reachableWithoutPeers.has(key);
109109+104110 packages.push({
105111 name: pkg.name,
106112 version: pkg.version,
···111117 dependencies,
112118 description: pkg.description,
113119 license: pkg.license,
114114- isPeer: !reachableWithoutPeers.has(key),
120120+ isPeer: isDirectPeerOfRoot || isOnlyReachableThroughPeers,
115121 });
116122 }
117123