-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add pnpm store visualization command (pnpm#7446)
close pnpm#7413
- Loading branch information
Showing
19 changed files
with
1,037 additions
and
485 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--- | ||
"@pnpm/plugin-commands-store-inspecting": patch | ||
"pnpm": patch | ||
--- | ||
|
||
New commands added for inspecting the store: | ||
|
||
* **pnpm cat-index**: Prints the index file of a specific package in the store. The package is specified by its name and version: `pnpm cat-index <pkg name>@<pkg version>` | ||
* **pnpm cat-file**: Prints the contents of a file based on the hash value stored in the index file. For example: | ||
``` | ||
pnpm cat-file sha512-mvavhfVcEREI7d8dfvfvIkuBLnx7+rrkHHnPi8mpEDUlNpY4CUY+CvJ5mrrLl18iQYo1odFwBV7z/cOypG7xxQ== | ||
``` | ||
* **pnpm find-hash**: Lists the packages that include the file with the specified hash. For example: | ||
``` | ||
pnpm find-hash sha512-mvavhfVcEREI7d8dfvfvIkuBLnx7+rrkHHnPi8mpEDUlNpY4CUY+CvJ5mrrLl18iQYo1odFwBV7z/cOypG7xxQ== | ||
``` | ||
This command is **experimental**. We might change how it behaves. | ||
|
||
Related issue: [#7413](https://github.com/pnpm/pnpm/issues/7413). |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# @pnpm/plugin-commands-store-inspecting | ||
|
||
> The inspecting store commands of pnpm | ||
[![npm version](https://img.shields.io/npm/v/@pnpm/plugin-commands-store-inspecting.svg)](https://www.npmjs.com/package/@pnpm/plugin-commands-store-inspecting) | ||
|
||
## Installation | ||
|
||
```sh | ||
pnpm add @pnpm/plugin-commands-store-inspecting | ||
``` | ||
|
||
## License | ||
|
||
MIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('../../jest-with-registry.config.js') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
{ | ||
"name": "@pnpm/plugin-commands-store-inspecting", | ||
"version": "0.0.0", | ||
"description": "The inspecting store commands of pnpm", | ||
"main": "lib/index.js", | ||
"types": "lib/index.d.ts", | ||
"files": [ | ||
"lib", | ||
"!*.map" | ||
], | ||
"engines": { | ||
"node": ">=16.14" | ||
}, | ||
"scripts": { | ||
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"", | ||
"_test": "jest", | ||
"test": "pnpm run compile && pnpm run _test", | ||
"prepublishOnly": "pnpm run compile", | ||
"compile": "tsc --build && pnpm run lint --fix" | ||
}, | ||
"repository": "https://github.com/pnpm/pnpm/blob/main/store/plugin-commands-store-inspecting", | ||
"keywords": [ | ||
"pnpm8", | ||
"pnpm" | ||
], | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/pnpm/pnpm/issues" | ||
}, | ||
"homepage": "https://github.com/pnpm/pnpm/blob/main/store/plugin-commands-store-inspecting#readme", | ||
"devDependencies": { | ||
"@pnpm/plugin-commands-store-inspecting": "workspace:*", | ||
"@pnpm/prepare": "workspace:*", | ||
"tempy": "^1.0.1", | ||
"execa": "npm:safe-execa@0.1.2" | ||
}, | ||
"dependencies": { | ||
"@pnpm/config": "workspace:*", | ||
"@pnpm/error": "workspace:*", | ||
"@pnpm/types": "workspace:*", | ||
"@pnpm/client": "workspace:*", | ||
"@pnpm/parse-wanted-dependency": "workspace:*", | ||
"@pnpm/pick-registry-for-package": "workspace:*", | ||
"@pnpm/store.cafs": "workspace:*", | ||
"@pnpm/lockfile-types": "workspace:*", | ||
"@pnpm/store-path": "workspace:*", | ||
"@pnpm/graceful-fs": "workspace:*", | ||
"load-json-file": "^6.2.0", | ||
"render-help": "^1.0.3", | ||
"chalk": "^4.1.2" | ||
}, | ||
"funding": "https://opencollective.com/pnpm", | ||
"exports": { | ||
".": "./lib/index.js" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import path from 'path' | ||
|
||
import { type Config } from '@pnpm/config' | ||
import { PnpmError } from '@pnpm/error' | ||
import gfs from '@pnpm/graceful-fs' | ||
import { getStorePath } from '@pnpm/store-path' | ||
|
||
import renderHelp from 'render-help' | ||
|
||
const INTEGRITY_REGEX: RegExp = /^([^-]+)-([A-Za-z0-9+/=]+)$/ | ||
|
||
export const commandNames = ['cat-file'] | ||
|
||
export const rcOptionsTypes = cliOptionsTypes | ||
|
||
export function cliOptionsTypes () { | ||
return {} | ||
} | ||
|
||
export function help () { | ||
return renderHelp({ | ||
description: | ||
'Prints the contents of a file based on the hash value stored in the index file.', | ||
descriptionLists: [], | ||
usages: ['pnpm cat-file <hash>'], | ||
}) | ||
} | ||
|
||
export type CatFileCommandOptions = Pick<Config, 'storeDir' | 'pnpmHomeDir'> | ||
|
||
export async function handler (opts: CatFileCommandOptions, params: string[]) { | ||
if (!params || params.length === 0) { | ||
throw new PnpmError('MISSING_HASH', 'Missing file hash', { | ||
hint: help(), | ||
}) | ||
} | ||
|
||
const [, , integrityHash] = params[0].match(INTEGRITY_REGEX)! | ||
|
||
const toHex = Buffer.from(integrityHash, 'base64').toString('hex') | ||
const storeDir = await getStorePath({ | ||
pkgRoot: process.cwd(), | ||
storePath: opts.storeDir, | ||
pnpmHomeDir: opts.pnpmHomeDir, | ||
}) | ||
const cafsDir = path.join(storeDir, 'files') | ||
const filePath = path.resolve(cafsDir, toHex.slice(0, 2), toHex.slice(2)) | ||
|
||
try { | ||
return gfs.readFileSync(filePath, 'utf8') | ||
} catch (err: any) { // eslint-disable-line | ||
if (err.code === 'ENOENT') { | ||
throw new PnpmError('INVALID_HASH', 'Corresponding hash file not found') | ||
} | ||
throw err | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import path from 'path' | ||
|
||
import { type Config } from '@pnpm/config' | ||
import { createResolver } from '@pnpm/client' | ||
import { type TarballResolution } from '@pnpm/lockfile-types' | ||
|
||
import { PnpmError } from '@pnpm/error' | ||
import { getStorePath } from '@pnpm/store-path' | ||
import { getFilePathInCafs, type PackageFilesIndex } from '@pnpm/store.cafs' | ||
import { pickRegistryForPackage } from '@pnpm/pick-registry-for-package' | ||
import { parseWantedDependency } from '@pnpm/parse-wanted-dependency' | ||
|
||
import loadJsonFile from 'load-json-file' | ||
import renderHelp from 'render-help' | ||
|
||
export const commandNames = ['cat-index'] | ||
|
||
export const rcOptionsTypes = cliOptionsTypes | ||
|
||
export function cliOptionsTypes () { | ||
return {} | ||
} | ||
|
||
export function help () { | ||
return renderHelp({ | ||
description: 'Prints the index file of a specific package from the store.', | ||
descriptionLists: [], | ||
usages: ['pnpm cat-index <pkg name>@<pkg version>'], | ||
}) | ||
} | ||
|
||
export type CatIndexCommandOptions = Pick< | ||
Config, | ||
| 'rawConfig' | ||
| 'pnpmHomeDir' | ||
| 'storeDir' | ||
| 'lockfileDir' | ||
| 'dir' | ||
| 'registries' | ||
| 'cacheDir' | ||
> | ||
|
||
export async function handler (opts: CatIndexCommandOptions, params: string[]) { | ||
if (!params || params.length === 0) { | ||
throw new PnpmError( | ||
'MISSING_PACKAGE_NAME', | ||
'Specify a package', | ||
{ | ||
hint: help(), | ||
} | ||
) | ||
} | ||
|
||
const wantedDependency = params[0] | ||
const { alias, pref } = parseWantedDependency(wantedDependency) || {} | ||
|
||
if (!alias) { | ||
throw new PnpmError( | ||
'INVALID_SELECTOR', | ||
`Cannot parse the "${wantedDependency}" selector` | ||
) | ||
} | ||
|
||
const storeDir = await getStorePath({ | ||
pkgRoot: process.cwd(), | ||
storePath: opts.storeDir, | ||
pnpmHomeDir: opts.pnpmHomeDir, | ||
}) | ||
const cafsDir = path.join(storeDir, 'files') | ||
const resolve = createResolver({ | ||
...opts, | ||
authConfig: opts.rawConfig, | ||
}) | ||
const pkgSnapshot = await resolve( | ||
{ alias, pref }, | ||
{ | ||
lockfileDir: opts.lockfileDir ?? opts.dir, | ||
preferredVersions: {}, | ||
projectDir: opts.dir, | ||
registry: pickRegistryForPackage(opts.registries, alias, pref), | ||
} | ||
) | ||
|
||
const filesIndexFile = getFilePathInCafs( | ||
cafsDir, | ||
(pkgSnapshot.resolution as TarballResolution).integrity!.toString(), | ||
'index' | ||
) | ||
try { | ||
const pkgFilesIndex = await loadJsonFile<PackageFilesIndex>(filesIndexFile) | ||
return JSON.stringify(pkgFilesIndex, null, 2) | ||
} catch { | ||
throw new PnpmError( | ||
'INVALID_PACKAGE', | ||
'No corresponding index file found. You can use pnpm list to see if the package is installed.' | ||
) | ||
} | ||
} |
Oops, something went wrong.