feat: add pnpm doctor command to do checks for known common issues (#5526)

This commit is contained in:
chlorine
2022-10-22 19:08:22 +08:00
committed by GitHub
parent 804de211ea
commit bea0acdfcb
17 changed files with 214 additions and 13 deletions

View File

@@ -0,0 +1,7 @@
---
"@pnpm/plugin-commands-doctor": major
"pnpm": minor
"@pnpm/config": patch
---
Add `pnpm doctor` command to do checks for known common issues

View File

@@ -36,7 +36,7 @@
"@pnpm/error": "workspace:*",
"@pnpm/git-utils": "workspace:*",
"@pnpm/matcher": "workspace:*",
"@pnpm/npm-conf": "2.0.0",
"@pnpm/npm-conf": "2.0.2",
"@pnpm/pnpmfile": "workspace:*",
"@pnpm/read-project-manifest": "workspace:*",
"@pnpm/types": "workspace:*",

View File

@@ -86,6 +86,7 @@ export interface Config {
preferSymlinkedExecutables?: boolean
resolutionMode?: 'highest' | 'time-based'
registrySupportsTimeField?: boolean
failedToLoadBuiltInConfig: boolean
// proxy
httpProxy?: string

View File

@@ -181,7 +181,7 @@ export async function getConfig (
cliOptions['prefix'] = cliOptions.dir // the npm config system still expects `prefix`
}
const rcOptionsTypes = { ...types, ...opts.rcOptionsTypes }
const { config: npmConfig, warnings } = loadNpmConf(cliOptions, rcOptionsTypes, {
const { config: npmConfig, warnings, failedToLoadBuiltInConfig } = loadNpmConf(cliOptions, rcOptionsTypes, {
'auto-install-peers': false,
bail: true,
color: 'auto',
@@ -526,6 +526,8 @@ export async function getConfig (
}
pnpmConfig.rootProjectManifest = await safeReadProjectManifestOnly(pnpmConfig.lockfileDir ?? pnpmConfig.dir) ?? undefined
pnpmConfig.failedToLoadBuiltInConfig = failedToLoadBuiltInConfig
return { config: pnpmConfig, warnings }
}

View File

@@ -929,3 +929,15 @@ test('return a warning when the .npmrc has an env variable that does not exist',
expect(warnings).toEqual(expect.arrayContaining(expected))
})
test('getConfig() returns failedToLoadBuiltInConfig', async () => {
const { config } = await getConfig({
cliOptions: {},
packageManager: {
name: 'pnpm',
version: '1.0.0',
},
})
expect(config.failedToLoadBuiltInConfig).toBeDefined()
})

View File

@@ -0,0 +1,15 @@
# @pnpm/plugin-commands-doctor
> pnpm commands for checks of known common issues
[![npm version](https://img.shields.io/npm/v/@pnpm/plugin-commands-doctor.svg)](https://www.npmjs.com/package/@pnpm/plugin-commands-doctor)
## Installation
```sh
pnpm add @pnpm/plugin-commands-doctor
```
## License
MIT

View File

@@ -0,0 +1 @@
module.exports = require('../../jest.config.js')

View File

@@ -0,0 +1,47 @@
{
"name": "@pnpm/plugin-commands-doctor",
"version": "0.0.0",
"description": "Commands for checks of known common issues ",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib",
"!*.map"
],
"engines": {
"node": ">=14.6"
},
"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/packages/plugin-commands-doctor",
"keywords": [
"pnpm7",
"pnpm",
"doctor"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/pnpm/pnpm/issues"
},
"homepage": "https://github.com/pnpm/pnpm/blob/main/packages/plugin-commands-doctor#readme",
"dependencies": {
"@pnpm/cli-utils": "workspace:*",
"@pnpm/config": "workspace:*",
"render-help": "^1.0.2"
},
"peerDependencies": {
"@pnpm/logger": "^5.0.0"
},
"devDependencies": {
"@pnpm/plugin-commands-doctor": "workspace:*"
},
"funding": "https://opencollective.com/pnpm",
"exports": {
".": "./lib/index.js"
}
}

View File

@@ -0,0 +1,35 @@
import renderHelp from 'render-help'
import { docsUrl } from '@pnpm/cli-utils'
import { logger } from '@pnpm/logger'
import { Config } from '@pnpm/config'
export const rcOptionsTypes = cliOptionsTypes
export function cliOptionsTypes () {
return {}
}
export const shorthands = {}
export const commandNames = ['doctor']
export function help () {
return renderHelp({
description: 'Checks for known common issues.',
url: docsUrl('doctor'),
usages: ['pnpm doctor [options]'],
})
}
export async function handler (
opts: Pick<Config, 'failedToLoadBuiltInConfig'>
) {
const { failedToLoadBuiltInConfig } = opts
if (failedToLoadBuiltInConfig) {
// If true, means loading npm builtin config failed. Then there may have a prefix error, related: https://github.com/pnpm/pnpm/issues/5404
logger.warn({
message: 'Load npm builtin configs failed. If the prefix builtin config does not work, you can use "pnpm config ls" to show builtin configs. And then use "pnpm config --global set <key> <value>" to migrate configs from builtin to global.',
prefix: process.cwd(),
})
}
}

View File

@@ -0,0 +1,3 @@
import * as doctor from './doctor'
export { doctor }

View File

@@ -0,0 +1,22 @@
import { doctor } from '@pnpm/plugin-commands-doctor'
import { logger } from '@pnpm/logger'
beforeEach(() => {
jest.spyOn(logger, 'warn')
})
afterEach(() => {
(logger.warn as jest.Mock).mockRestore()
})
test('doctor', async () => {
// In the scope of jest, require.resolve.paths('npm') cannot reach global npm path by default
await doctor.handler({
failedToLoadBuiltInConfig: true,
})
expect(logger.warn).toHaveBeenCalledWith({
message: expect.stringMatching(/^Load npm builtin configs failed./),
prefix: process.cwd(),
})
})

View File

@@ -0,0 +1,19 @@
{
"extends": "@pnpm/tsconfig",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src"
},
"include": [
"src/**/*.ts",
"../../typings/**/*.d.ts"
],
"references": [
{
"path": "../cli-utils"
},
{
"path": "../config"
}
]
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"include": [
"src/**/*.ts",
"test/**/*.ts",
"../../typings/**/*.d.ts"
]
}

View File

@@ -41,6 +41,7 @@
"@pnpm/pick-registry-for-package": "workspace:*",
"@pnpm/plugin-commands-audit": "workspace:*",
"@pnpm/plugin-commands-deploy": "workspace:*",
"@pnpm/plugin-commands-doctor": "workspace:*",
"@pnpm/plugin-commands-env": "workspace:*",
"@pnpm/plugin-commands-init": "workspace:*",
"@pnpm/plugin-commands-installation": "workspace:*",

View File

@@ -1,6 +1,7 @@
import { CompletionFunc } from '@pnpm/command'
import { types as allTypes } from '@pnpm/config'
import { audit } from '@pnpm/plugin-commands-audit'
import { doctor } from '@pnpm/plugin-commands-doctor'
import { env } from '@pnpm/plugin-commands-env'
import { deploy } from '@pnpm/plugin-commands-deploy'
import { add, fetch, install, link, prune, remove, unlink, update, importCommand } from '@pnpm/plugin-commands-installation'
@@ -100,6 +101,7 @@ const commands: CommandDefinition[] = [
create,
deploy,
dlx,
doctor,
env,
exec,
fetch,

View File

@@ -78,6 +78,9 @@
{
"path": "../plugin-commands-deploy"
},
{
"path": "../plugin-commands-doctor"
},
{
"path": "../plugin-commands-env"
},

45
pnpm-lock.yaml generated
View File

@@ -491,8 +491,8 @@ importers:
specifier: workspace:*
version: link:../matcher
'@pnpm/npm-conf':
specifier: 2.0.0
version: 2.0.0
specifier: 2.0.2
version: 2.0.2
'@pnpm/pnpmfile':
specifier: workspace:*
version: link:../pnpmfile
@@ -3113,6 +3113,25 @@ importers:
specifier: 3.1.0
version: 3.1.0_typanion@3.12.0
packages/plugin-commands-doctor:
dependencies:
'@pnpm/cli-utils':
specifier: workspace:*
version: link:../cli-utils
'@pnpm/config':
specifier: workspace:*
version: link:../config
'@pnpm/logger':
specifier: ^5.0.0
version: 5.0.0
render-help:
specifier: ^1.0.2
version: 1.0.2
devDependencies:
'@pnpm/plugin-commands-doctor':
specifier: workspace:*
version: 'link:'
packages/plugin-commands-env:
dependencies:
'@pnpm/cli-utils':
@@ -4289,6 +4308,9 @@ importers:
'@pnpm/plugin-commands-deploy':
specifier: workspace:*
version: link:../plugin-commands-deploy
'@pnpm/plugin-commands-doctor':
specifier: workspace:*
version: link:../plugin-commands-doctor
'@pnpm/plugin-commands-env':
specifier: workspace:*
version: link:../plugin-commands-env
@@ -7430,14 +7452,6 @@ packages:
normalize-registry-url: 2.0.0
dev: true
/@pnpm/npm-conf/2.0.0:
resolution: {integrity: sha512-Ot3xJvdbRQ3fwtDeRYMik/97BbCKij9ZupSgY1tJLCzPPgYRTIIjwdOBHQX2qGbwqNeKd6EneMyKAAsUMO09Bw==}
engines: {node: '>=12'}
dependencies:
'@pnpm/network.ca-file': 1.0.1
config-chain: 1.1.13
dev: false
/@pnpm/npm-conf/2.0.1:
resolution: {integrity: sha512-3+0d2togeuHF4WNfjMLK0MPiM2nqX31dYoaQhLTl5fNmFzn2iciB/MGs1LNMM34bcty6PYoSq0sFI77GfJ1D8g==}
engines: {node: '>=12'}
@@ -7446,6 +7460,14 @@ packages:
config-chain: 1.1.13
dev: true
/@pnpm/npm-conf/2.0.2:
resolution: {integrity: sha512-vp0T6HQcklEpSILEutr8o4Gxf3lIPJtxbDT1kGNyYo0ZVL1UGgazeaGr9rc4ut8veI7tiVCBr7cJbDgym/q3Kg==}
engines: {node: '>=12'}
dependencies:
'@pnpm/network.ca-file': 1.0.1
config-chain: 1.1.13
dev: false
/@pnpm/npm-lifecycle/2.0.0-1_typanion@3.12.0:
resolution: {integrity: sha512-eUeRVUxnr9xP50ESMuRDrWYN/AQmaV2g/Wvs3ckHBx7XFJw8ljix66L7R1S1FoUqxNn0BeyPeIE9ANwn/syIAQ==}
engines: {node: '>=12.17'}
@@ -16739,6 +16761,7 @@ packages:
/w3c-hr-time/1.0.2:
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
deprecated: Use your platform's native performance.now() and performance.timeOrigin.
dependencies:
browser-process-hrtime: 1.0.0
@@ -17127,7 +17150,7 @@ time:
/@pnpm/meta-updater/0.2.1: '2022-10-17T23:32:30.921Z'
/@pnpm/network.agent/0.0.3: '2022-06-12T19:51:53.044Z'
/@pnpm/nopt/0.2.1: '2021-06-01T19:45:54.552Z'
/@pnpm/npm-conf/2.0.0: '2022-07-31T00:06:52.248Z'
/@pnpm/npm-conf/2.0.2: '2022-10-21T14:43:04.271Z'
/@pnpm/npm-lifecycle/2.0.0-1: '2022-02-21T22:36:47.308Z'
/@pnpm/npm-package-arg/1.0.0: '2022-06-28T12:48:31.287Z'
/@pnpm/os.env.path-extender/0.2.7: '2022-10-17T23:03:23.674Z'