simonbuchan / pnpm-extra

A small CLI `pnpm-extra` which adds some commands missing from pnpm
MIT License
1 stars 1 forks source link

Subcommand to print the directory of a package in node_modules #2

Open jayvdb opened 15 hours ago

jayvdb commented 15 hours ago

I'm wondering whether this project might be a suitable home for some existing pnpm functionality I have.

I need a lib function that provides only the directory name inside of node_modules for a top-level dependency, so that I can inspect the released files of the dependency. This could be CLI subcommand something like pnpm-extra where-is <package name>

Currently my implementation invokes pnpm list --json --long <package_name> and parses the json output to get the path.

e.g.

> pnpm list --json --long ol
[
  {
    "name": "top-level-package-name",
    "version": "1.0.22",
    "path": "/home/jayvdb/work/top-level-frontend-project",
    "private": false,
    "dependencies": {
      "ol": {
        "from": "ol",
        "version": "10.1.0",
        "resolved": "https://registry.npmjs.org/ol/-/ol-10.1.0.tgz",
        "description": "OpenLayers mapping library",
        "license": "BSD-2-Clause",
        "homepage": "https://openlayers.org/",
        "repository": "git://github.com/openlayers/openlayers.git",
        "path": "/home/jayvdb/work/top-level-frontend-project/node_modules/.pnpm/ol@10.1.0/node_modules/ol"
      }
    }
  }
]

I need only /home/jayvdb/work/top-level-frontend-project/node_modules/.pnpm/ol@10.1.0/node_modules/ol so I can go look in there.

Another way to achieve this is to read the symlinks pnpm creates

> ls -ald node_modules/ol
lrwxrwxrwx 1 jayvdb jayvdb 31 Sep 19 09:10 node_modules/ol -> .pnpm/ol@10.1.0/node_modules/ol
> ls -ald node_modules/@eslint/*
lrwxrwxrwx 1 jayvdb jayvdb 61 Sep  9 06:57 node_modules/@eslint/eslintrc -> ../.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc
lrwxrwxrwx 1 jayvdb jayvdb 50 Sep  9 06:57 node_modules/@eslint/js -> ../.pnpm/@eslint+js@8.57.0/node_modules/@eslint/js

However both of those approaches only work for top-level dependencies

I am very happy to contribute my wrapper around pnpm list .. , or this could be written without the need for invoking pnpm but that requires either using the symlinks created by pnpm (which would require running tests also on Windows to verify it works there).

Another option is to add logic about how pnpm decides where to put each package inside node_modules, which doesnt look too hard to replicate, but might be a bit brittle if pnpm changes this, and I believe pnpm already supports a few layouts, at least one additional one to provide compatibility with npm style layout.

simonbuchan commented 15 hours ago

The virtual store (.pnpm) directory layout itself is fairly constrained due to node lookup logic, most of the wiggle room pnpm has is around what versions to share, especially around peer dependencies.

That information is flatly represented in the lock file as the extended version and the resolutions, so if you have a way to select an entry in there (itself a decently complex issue as it's an arbitrary directed graph, possibly even including cycles!) then the path is pretty simple to build, and no more exposed to pnpm changes than the existing parsing that tree is doing.

I'm happy to poke at this, though probably after i figure out how to get a release bot for crates going now this is a library...