diff --git a/.changeset/moody-rice-own.md b/.changeset/moody-rice-own.md new file mode 100644 index 0000000000..227a17b21c --- /dev/null +++ b/.changeset/moody-rice-own.md @@ -0,0 +1,5 @@ +--- +"@pnpm/error": minor +--- + +Add new optional field: prefix. diff --git a/.changeset/twelve-ties-push.md b/.changeset/twelve-ties-push.md new file mode 100644 index 0000000000..922b3b5488 --- /dev/null +++ b/.changeset/twelve-ties-push.md @@ -0,0 +1,7 @@ +--- +"@pnpm/default-reporter": patch +"@pnpm/resolve-dependencies": patch +"pnpm": patch +--- + +When a direct dependency fails to resolve, print the path to the project directory in the error message. diff --git a/packages/core/test/install/misc.ts b/packages/core/test/install/misc.ts index b85f893cea..3214376706 100644 --- a/packages/core/test/install/misc.ts +++ b/packages/core/test/install/misc.ts @@ -1114,6 +1114,7 @@ test('fail if none of the available resolvers support a version spec', async () err = _err } expect(err.code).toBe('ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER') + expect(err.prefix).toBe(process.cwd()) expect(err.pkgsStack).toStrictEqual( [ { diff --git a/packages/default-reporter/src/reportError.ts b/packages/default-reporter/src/reportError.ts index 33f741aa82..aba8ec15ca 100644 --- a/packages/default-reporter/src/reportError.ts +++ b/packages/default-reporter/src/reportError.ts @@ -20,8 +20,12 @@ const colorPath = chalk.gray export default function reportError (logObj: Log, config?: Config) { const errorInfo = getErrorInfo(logObj, config) let output = formatErrorSummary(errorInfo.title, logObj['err']['code']) - if (logObj['pkgsStack']?.length) { - output += `\n\n${formatPkgsStack(logObj['pkgsStack'])}` + if (logObj['pkgsStack'] != null) { + if (logObj['pkgsStack'].length > 0) { + output += `\n\n${formatPkgsStack(logObj['pkgsStack'])}` + } else if (logObj['prefix']) { + output += `\n\nThis error happened while installing a direct dependency of ${logObj['prefix'] as string}` + } } if (errorInfo.body) { output += `\n\n${errorInfo.body}` diff --git a/packages/default-reporter/test/reportingErrors.ts b/packages/default-reporter/test/reportingErrors.ts index bd7e087258..cb76d82d6f 100644 --- a/packages/default-reporter/test/reportingErrors.ts +++ b/packages/default-reporter/test/reportingErrors.ts @@ -128,7 +128,8 @@ test('prints suggestions when an internet-connection related error happens', (do complete: () => done(), error: done, next: output => { - expect(output).toBe(`${formatError('ERR_PNPM_BAD_TARBALL_SIZE', 'Actual size (99) of tarball (https://foo) did not match the one specified in \'Content-Length\' header (100)')} + expect(output).toBe(`/project-dir: +${formatError('ERR_PNPM_BAD_TARBALL_SIZE', 'Actual size (99) of tarball (https://foo) did not match the one specified in \'Content-Length\' header (100)')} ${ERROR_PAD} ${ERROR_PAD}This error happened while installing the dependencies of foo@1.0.0 ${ERROR_PAD} @@ -150,6 +151,7 @@ ${ERROR_PAD}For instance, \`pnpm install --fetch-retries 5 --network-concurrency }) const err = new PnpmError('BAD_TARBALL_SIZE', 'Actual size (99) of tarball (https://foo) did not match the one specified in \'Content-Length\' header (100)') + err.prefix = '/project-dir' err.pkgsStack = [ { id: 'registry.npmjs.org/foo/1.0.0', @@ -355,13 +357,14 @@ test('prints error even if the error object not passed in through the message ob }) }) -test('prints error without packages stacktrace when pkgsStack is empty', (done) => { +test('prints error without packages stacktrace when pkgsStack is empty but do print the project directory path', (done) => { const output$ = toOutput$({ context: { argv: ['install'] }, streamParser: createStreamParser(), }) const err = new PnpmError('SOME_ERROR', 'some error') + err.prefix = '/project-dir' err.pkgsStack = [] logger.error(err, err) @@ -371,7 +374,10 @@ test('prints error without packages stacktrace when pkgsStack is empty', (done) complete: () => done(), error: done, next: output => { - expect(output).toBe(formatError('ERR_PNPM_SOME_ERROR', 'some error')) + expect(output).toBe(`/project-dir: +${formatError('ERR_PNPM_SOME_ERROR', 'some error')} +${ERROR_PAD} +${ERROR_PAD}This error happened while installing a direct dependency of /project-dir`) }, }) }) @@ -413,6 +419,7 @@ test('prints error with packages stacktrace - depth 2', (done) => { }) const err = new PnpmError('SOME_ERROR', 'some error') + err.prefix = '/project-dir' err.pkgsStack = [ { id: 'registry.npmjs.org/foo/1.0.0', @@ -433,7 +440,8 @@ test('prints error with packages stacktrace - depth 2', (done) => { complete: () => done(), error: done, next: output => { - expect(output).toBe(`${formatError('ERR_PNPM_SOME_ERROR', 'some error')} + expect(output).toBe(`/project-dir: +${formatError('ERR_PNPM_SOME_ERROR', 'some error')} ${ERROR_PAD} ${ERROR_PAD}This error happened while installing the dependencies of foo@1.0.0 ${ERROR_PAD} at bar@1.0.0`) diff --git a/packages/error/src/index.ts b/packages/error/src/index.ts index 8a7e02faab..7b24b6c1e1 100644 --- a/packages/error/src/index.ts +++ b/packages/error/src/index.ts @@ -4,6 +4,7 @@ export default class PnpmError extends Error { public readonly code: string public readonly hint?: string public attempts?: number + public prefix?: string public pkgsStack?: Array<{ id: string, name: string, version: string }> constructor ( code: string, diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index c9b0450063..f3bf7b6fd5 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -1067,6 +1067,7 @@ async function resolveDependency ( }) return null } + err.prefix = options.prefix err.pkgsStack = nodeIdToParents(options.parentPkg.nodeId, ctx.resolvedPackagesByDepPath) throw err }