@pnpm/deps.inspection.commands 1100.1.13 → 1100.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/bugs/index.d.ts +8 -0
- package/lib/bugs/index.js +99 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/view/index.js +72 -20
- package/package.json +28 -26
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Config, type ConfigContext } from '@pnpm/config.reader';
|
|
2
|
+
export declare function rcOptionsTypes(): Record<string, unknown>;
|
|
3
|
+
export declare function cliOptionsTypes(): Record<string, unknown>;
|
|
4
|
+
export declare const commandNames: string[];
|
|
5
|
+
export declare function help(): string;
|
|
6
|
+
export declare function handler(opts: Config & ConfigContext & {
|
|
7
|
+
dir: string;
|
|
8
|
+
}, params: string[]): Promise<void>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { docsUrl, readProjectManifestOnly } from '@pnpm/cli.utils';
|
|
2
|
+
import { types as allTypes } from '@pnpm/config.reader';
|
|
3
|
+
import { PnpmError } from '@pnpm/error';
|
|
4
|
+
import HostedGit from 'hosted-git-info';
|
|
5
|
+
import open from 'open';
|
|
6
|
+
import { pick } from 'ramda';
|
|
7
|
+
import { renderHelp } from 'render-help';
|
|
8
|
+
import { fetchPackageInfo } from '../fetchPackageInfo.js';
|
|
9
|
+
export function rcOptionsTypes() {
|
|
10
|
+
return pick(['registry'], allTypes);
|
|
11
|
+
}
|
|
12
|
+
export function cliOptionsTypes() {
|
|
13
|
+
return rcOptionsTypes();
|
|
14
|
+
}
|
|
15
|
+
export const commandNames = ['bugs'];
|
|
16
|
+
export function help() {
|
|
17
|
+
return renderHelp({
|
|
18
|
+
description: "Opens the URL of the package's bug tracker in a browser.",
|
|
19
|
+
url: docsUrl('bugs'),
|
|
20
|
+
usages: ['pnpm bugs [<pkgname> [<pkgname> ...]]'],
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export async function handler(opts, params) {
|
|
24
|
+
const urls = params.length === 0
|
|
25
|
+
? [await getBugsUrlFromCurrentProject(opts)]
|
|
26
|
+
: await Promise.all(params.map((spec) => getBugsUrlFromRegistry(opts, spec)));
|
|
27
|
+
for (const url of urls) {
|
|
28
|
+
// eslint-disable-next-line no-await-in-loop
|
|
29
|
+
await open(url);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function getBugsUrlFromCurrentProject(opts) {
|
|
33
|
+
const manifest = await readProjectManifestOnly(opts.dir, {
|
|
34
|
+
engineStrict: opts.engineStrict,
|
|
35
|
+
nodeVersion: opts.nodeVersion,
|
|
36
|
+
supportedArchitectures: opts.supportedArchitectures,
|
|
37
|
+
});
|
|
38
|
+
const url = pickBugsUrl({ bugs: manifest.bugs, repository: manifest.repository });
|
|
39
|
+
if (!url) {
|
|
40
|
+
throw new PnpmError('NO_BUGS_URL', 'The current project does not have a bug tracker URL. Add a "bugs" or "repository" field to its manifest.');
|
|
41
|
+
}
|
|
42
|
+
return url;
|
|
43
|
+
}
|
|
44
|
+
async function getBugsUrlFromRegistry(opts, packageSpec) {
|
|
45
|
+
const info = await fetchPackageInfo(opts, packageSpec);
|
|
46
|
+
const url = pickBugsUrl({ bugs: info.bugs, repository: info.repository });
|
|
47
|
+
if (!url) {
|
|
48
|
+
throw new PnpmError('NO_BUGS_URL', `The package "${info.name}" does not have a bug tracker URL.`);
|
|
49
|
+
}
|
|
50
|
+
return url;
|
|
51
|
+
}
|
|
52
|
+
function pickBugsUrl(manifest) {
|
|
53
|
+
if (manifest.bugs) {
|
|
54
|
+
const bugsUrl = typeof manifest.bugs === 'string' ? manifest.bugs : manifest.bugs.url;
|
|
55
|
+
if (bugsUrl && isHttpUrl(bugsUrl))
|
|
56
|
+
return bugsUrl;
|
|
57
|
+
}
|
|
58
|
+
if (manifest.repository) {
|
|
59
|
+
const repoUrl = typeof manifest.repository === 'string' ? manifest.repository : manifest.repository.url;
|
|
60
|
+
if (repoUrl)
|
|
61
|
+
return repositoryToIssuesUrl(repoUrl);
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
function repositoryToIssuesUrl(rawUrl) {
|
|
66
|
+
// hosted-git-info handles GitHub/GitLab/Bitbucket/etc. shorthand and SSH forms
|
|
67
|
+
// (`owner/repo`, `github:owner/repo`, `git+ssh://git@github.com/owner/repo.git`,
|
|
68
|
+
// `git@github.com:owner/repo.git`, …) and yields the canonical bugs URL directly.
|
|
69
|
+
const hosted = HostedGit.fromUrl(rawUrl);
|
|
70
|
+
if (hosted != null) {
|
|
71
|
+
const url = hosted.bugs();
|
|
72
|
+
if (url && isHttpUrl(url))
|
|
73
|
+
return url;
|
|
74
|
+
}
|
|
75
|
+
// Fallback for self-hosted git servers that hosted-git-info doesn't recognize.
|
|
76
|
+
let parsed;
|
|
77
|
+
try {
|
|
78
|
+
parsed = new URL(rawUrl.replace(/^git\+/, ''));
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
|
|
84
|
+
return undefined;
|
|
85
|
+
parsed.search = '';
|
|
86
|
+
parsed.hash = '';
|
|
87
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/, '').replace(/\.git$/, '') + '/issues';
|
|
88
|
+
return parsed.toString();
|
|
89
|
+
}
|
|
90
|
+
function isHttpUrl(value) {
|
|
91
|
+
try {
|
|
92
|
+
const { protocol } = new URL(value);
|
|
93
|
+
return protocol === 'http:' || protocol === 'https:';
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
package/lib/view/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { types as allTypes } from '@pnpm/config.reader';
|
|
2
2
|
import { PnpmError } from '@pnpm/error';
|
|
3
|
+
import { formatTimeAgo } from '@pnpm/resolving.npm-resolver';
|
|
4
|
+
import chalk from 'chalk';
|
|
3
5
|
import { pick } from 'ramda';
|
|
4
6
|
import { renderHelp } from 'render-help';
|
|
5
7
|
import { fetchPackageInfo } from '../fetchPackageInfo.js';
|
|
@@ -74,67 +76,74 @@ export async function handler(opts, params) {
|
|
|
74
76
|
}
|
|
75
77
|
const headerParts = [];
|
|
76
78
|
if (info.name && info.version) {
|
|
77
|
-
headerParts.push(`${info.name}@${info.version}`);
|
|
79
|
+
headerParts.push(chalk.cyan(`${info.name}@${info.version}`));
|
|
78
80
|
}
|
|
79
81
|
if (info.license) {
|
|
80
|
-
headerParts.push(info.license);
|
|
82
|
+
headerParts.push(chalk.green(info.license));
|
|
81
83
|
}
|
|
82
84
|
if (info.depsCount !== undefined) {
|
|
83
|
-
headerParts.push(`deps: ${info.depsCount}`);
|
|
85
|
+
headerParts.push(`deps: ${chalk.cyan(info.depsCount)}`);
|
|
84
86
|
}
|
|
85
87
|
else {
|
|
86
88
|
headerParts.push('deps: none');
|
|
87
89
|
}
|
|
88
90
|
if (info.versionsCount !== undefined) {
|
|
89
|
-
headerParts.push(`versions: ${info.versionsCount}`);
|
|
91
|
+
headerParts.push(`versions: ${chalk.cyan(info.versionsCount)}`);
|
|
90
92
|
}
|
|
91
93
|
const lines = [headerParts.join(' | ')];
|
|
92
94
|
if (info.description) {
|
|
93
95
|
lines.push(info.description);
|
|
94
96
|
}
|
|
95
97
|
if (info.homepage) {
|
|
96
|
-
lines.push(info.homepage);
|
|
98
|
+
lines.push(chalk.underline.blue(info.homepage));
|
|
97
99
|
}
|
|
98
100
|
if (info.keywords && info.keywords.length > 0) {
|
|
99
101
|
lines.push('');
|
|
100
|
-
lines.push(`keywords: ${info.keywords.join(', ')}`);
|
|
101
|
-
}
|
|
102
|
-
if (info.dependencies && Object.keys(info.dependencies).length > 0) {
|
|
103
|
-
lines.push('');
|
|
104
|
-
lines.push('dependencies:');
|
|
105
|
-
const depEntries = Object.entries(info.dependencies).map(([name, version]) => `${name}: ${version}`);
|
|
106
|
-
lines.push(depEntries.join(', '));
|
|
102
|
+
lines.push(`keywords: ${chalk.cyan(info.keywords.join(', '))}`);
|
|
107
103
|
}
|
|
108
104
|
if (info.dist) {
|
|
109
105
|
lines.push('');
|
|
110
|
-
lines.push('dist');
|
|
106
|
+
lines.push(chalk.bold('dist'));
|
|
111
107
|
if (info.dist.tarball) {
|
|
112
|
-
lines.push(`.tarball: ${info.dist.tarball}`);
|
|
108
|
+
lines.push(`.tarball: ${chalk.underline.blue(info.dist.tarball)}`);
|
|
113
109
|
}
|
|
114
110
|
if (info.dist.shasum) {
|
|
115
|
-
lines.push(`.shasum: ${info.dist.shasum}`);
|
|
111
|
+
lines.push(`.shasum: ${chalk.green(info.dist.shasum)}`);
|
|
116
112
|
}
|
|
117
113
|
if (info.dist.integrity) {
|
|
118
|
-
lines.push(`.integrity: ${info.dist.integrity}`);
|
|
114
|
+
lines.push(`.integrity: ${chalk.green(info.dist.integrity)}`);
|
|
119
115
|
}
|
|
120
116
|
if (info.dist.unpackedSize != null) {
|
|
121
|
-
lines.push(`.unpackedSize: ${formatBytes(info.dist.unpackedSize)}`);
|
|
117
|
+
lines.push(`.unpackedSize: ${chalk.blue(formatBytes(info.dist.unpackedSize))}`);
|
|
122
118
|
}
|
|
123
119
|
}
|
|
120
|
+
if (info.dependencies && Object.keys(info.dependencies).length > 0) {
|
|
121
|
+
lines.push('');
|
|
122
|
+
lines.push('dependencies:');
|
|
123
|
+
const depEntries = Object.entries(info.dependencies).map(([name, version]) => `${chalk.blue(name)}: ${version}`);
|
|
124
|
+
lines.push(depEntries.join(', '));
|
|
125
|
+
}
|
|
124
126
|
if (info.maintainers && info.maintainers.length > 0) {
|
|
125
127
|
lines.push('');
|
|
126
128
|
lines.push('maintainers:');
|
|
127
129
|
for (const maintainer of info.maintainers) {
|
|
128
|
-
|
|
130
|
+
const email = maintainer.email;
|
|
131
|
+
const name = email ? `${chalk.blue(maintainer.name)} <${chalk.dim(email)}>` : chalk.blue(maintainer.name);
|
|
132
|
+
lines.push(`- ${name}`);
|
|
129
133
|
}
|
|
130
134
|
}
|
|
131
135
|
if (info.distTags && Object.keys(info.distTags).length > 0) {
|
|
132
136
|
lines.push('');
|
|
133
|
-
lines.push('dist-tags:');
|
|
137
|
+
lines.push(chalk.bold('dist-tags:'));
|
|
134
138
|
for (const [tag, tagVersion] of Object.entries(info.distTags)) {
|
|
135
|
-
lines.push(`${tag}: ${tagVersion}`);
|
|
139
|
+
lines.push(`${chalk.blue(tag)}: ${tagVersion}`);
|
|
136
140
|
}
|
|
137
141
|
}
|
|
142
|
+
const publishedInfo = getPublishedInfo(info);
|
|
143
|
+
if (publishedInfo) {
|
|
144
|
+
lines.push('');
|
|
145
|
+
lines.push(publishedInfo);
|
|
146
|
+
}
|
|
138
147
|
return lines.join('\n');
|
|
139
148
|
}
|
|
140
149
|
function formatBytes(bytes) {
|
|
@@ -162,4 +171,47 @@ function formatFieldValue(value) {
|
|
|
162
171
|
}
|
|
163
172
|
return String(value);
|
|
164
173
|
}
|
|
174
|
+
function getPublishedInfo(info) {
|
|
175
|
+
if (!info.version || !info.time) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
const publishedTime = info.time[info.version];
|
|
179
|
+
if (!publishedTime) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
const publishedDate = new Date(publishedTime);
|
|
183
|
+
if (isNaN(publishedDate.getTime())) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
const timeAgo = formatTimeAgo(publishedDate) ?? 'just now';
|
|
187
|
+
const publisher = getPublisher(info);
|
|
188
|
+
if (publisher) {
|
|
189
|
+
return `published ${chalk.cyan(timeAgo)} by ${publisher}`;
|
|
190
|
+
}
|
|
191
|
+
return `published ${chalk.cyan(timeAgo)}`;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Retrieves the publisher name from package metadata.
|
|
195
|
+
* Checks fields in order: _npmUser, maintainers, author.
|
|
196
|
+
* Returns null if no publisher information is available.
|
|
197
|
+
*/
|
|
198
|
+
function getPublisher(info) {
|
|
199
|
+
if (info._npmUser?.name) {
|
|
200
|
+
const email = info._npmUser.email;
|
|
201
|
+
return email ? `${chalk.blue(info._npmUser.name)} <${chalk.dim(email)}>` : chalk.blue(info._npmUser.name);
|
|
202
|
+
}
|
|
203
|
+
if (info.maintainers && info.maintainers.length > 0) {
|
|
204
|
+
const first = info.maintainers[0];
|
|
205
|
+
const email = first.email;
|
|
206
|
+
const name = email ? `${chalk.blue(first.name)} <${chalk.dim(email)}>` : chalk.blue(first.name);
|
|
207
|
+
if (info.maintainers.length === 1) {
|
|
208
|
+
return name;
|
|
209
|
+
}
|
|
210
|
+
return `${name} et al.`;
|
|
211
|
+
}
|
|
212
|
+
if (info.author) {
|
|
213
|
+
return String(info.author);
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
165
217
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/deps.inspection.commands",
|
|
3
|
-
"version": "1100.1
|
|
3
|
+
"version": "1100.2.1",
|
|
4
4
|
"description": "The list, ll, why, and outdated commands of pnpm",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -28,51 +28,53 @@
|
|
|
28
28
|
"@pnpm/npm-package-arg": "^2.0.0",
|
|
29
29
|
"@pnpm/semver-diff": "^2.0.0",
|
|
30
30
|
"@zkochan/table": "^2.0.1",
|
|
31
|
-
"chalk": "^5.6.
|
|
31
|
+
"chalk": "^5.6.0",
|
|
32
|
+
"hosted-git-info": "npm:@pnpm/hosted-git-info@1.0.0",
|
|
32
33
|
"open": "^7.4.2",
|
|
33
34
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
34
35
|
"render-help": "^2.0.0",
|
|
35
36
|
"@pnpm/cli.command": "1100.0.1",
|
|
36
|
-
"@pnpm/cli.
|
|
37
|
-
"@pnpm/cli.utils": "1101.0.2",
|
|
37
|
+
"@pnpm/cli.utils": "1101.0.3",
|
|
38
38
|
"@pnpm/config.matcher": "1100.0.1",
|
|
39
|
-
"@pnpm/config.pick-registry-for-package": "1100.0.
|
|
40
|
-
"@pnpm/config.reader": "1101.
|
|
41
|
-
"@pnpm/deps.inspection.
|
|
42
|
-
"@pnpm/deps.inspection.
|
|
43
|
-
"@pnpm/deps.inspection.peers-
|
|
44
|
-
"@pnpm/deps.inspection.
|
|
45
|
-
"@pnpm/
|
|
39
|
+
"@pnpm/config.pick-registry-for-package": "1100.0.3",
|
|
40
|
+
"@pnpm/config.reader": "1101.3.0",
|
|
41
|
+
"@pnpm/deps.inspection.list": "1100.0.9",
|
|
42
|
+
"@pnpm/deps.inspection.peers-checker": "1100.0.7",
|
|
43
|
+
"@pnpm/deps.inspection.peers-issues-renderer": "1100.0.1",
|
|
44
|
+
"@pnpm/deps.inspection.outdated": "1100.0.14",
|
|
45
|
+
"@pnpm/cli.common-cli-options-help": "1100.0.1",
|
|
46
46
|
"@pnpm/error": "1100.0.0",
|
|
47
|
-
"@pnpm/global.packages": "1100.0.
|
|
48
|
-
"@pnpm/
|
|
49
|
-
"@pnpm/
|
|
50
|
-
"@pnpm/
|
|
51
|
-
"@pnpm/network.fetch": "1100.0.
|
|
52
|
-
"@pnpm/resolving.npm-resolver": "1101.0
|
|
53
|
-
"@pnpm/resolving.
|
|
47
|
+
"@pnpm/global.packages": "1100.0.3",
|
|
48
|
+
"@pnpm/global.commands": "1100.0.16",
|
|
49
|
+
"@pnpm/installing.modules-yaml": "1100.0.4",
|
|
50
|
+
"@pnpm/lockfile.fs": "1100.0.7",
|
|
51
|
+
"@pnpm/network.fetch": "1100.0.3",
|
|
52
|
+
"@pnpm/resolving.npm-resolver": "1101.1.0",
|
|
53
|
+
"@pnpm/resolving.registry.types": "1100.0.3",
|
|
54
|
+
"@pnpm/resolving.default-resolver": "1100.1.1",
|
|
54
55
|
"@pnpm/store.path": "1100.0.1",
|
|
55
|
-
"@pnpm/
|
|
56
|
-
"@pnpm/
|
|
56
|
+
"@pnpm/types": "1101.1.0",
|
|
57
|
+
"@pnpm/network.auth-header": "1100.0.2"
|
|
57
58
|
},
|
|
58
59
|
"peerDependencies": {
|
|
59
|
-
"@pnpm/logger": "
|
|
60
|
+
"@pnpm/logger": ">=1001.0.0 <1002.0.0"
|
|
60
61
|
},
|
|
61
62
|
"devDependencies": {
|
|
62
63
|
"@jest/globals": "30.3.0",
|
|
63
64
|
"@pnpm/registry-mock": "6.0.0",
|
|
65
|
+
"@types/hosted-git-info": "^3.0.5",
|
|
64
66
|
"@types/ramda": "0.31.1",
|
|
65
67
|
"@types/zkochan__table": "npm:@types/table@6.0.0",
|
|
66
68
|
"execa": "npm:safe-execa@0.3.0",
|
|
67
69
|
"symlink-dir": "^10.0.1",
|
|
68
70
|
"write-yaml-file": "^6.0.0",
|
|
69
71
|
"@pnpm/constants": "1100.0.0",
|
|
70
|
-
"@pnpm/deps.inspection.commands": "1100.1
|
|
71
|
-
"@pnpm/installing.commands": "1100.1.12",
|
|
72
|
-
"@pnpm/prepare": "1100.0.6",
|
|
73
|
-
"@pnpm/test-fixtures": "1100.0.0",
|
|
72
|
+
"@pnpm/deps.inspection.commands": "1100.2.1",
|
|
74
73
|
"@pnpm/testing.command-defaults": "1100.0.1",
|
|
75
|
-
"@pnpm/
|
|
74
|
+
"@pnpm/prepare": "1100.0.7",
|
|
75
|
+
"@pnpm/installing.commands": "1100.2.1",
|
|
76
|
+
"@pnpm/workspace.projects-filter": "1100.0.10",
|
|
77
|
+
"@pnpm/test-fixtures": "1100.0.0"
|
|
76
78
|
},
|
|
77
79
|
"engines": {
|
|
78
80
|
"node": ">=22.13"
|