Skip to content

Commit 3826665

Browse files
authored
feat: Search command improvements (#728)
* feat: added the page size option for search * feat: search results with rating and installs info * feat: added the publisher displayName to search * fix: addressed the PR comments
1 parent 194d59b commit 3826665

File tree

2 files changed

+64
-25
lines changed

2 files changed

+64
-25
lines changed

src/main.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { getLatestVersion } from './npm';
99
import { CancellationToken, log } from './util';
1010
import * as semver from 'semver';
1111
import { isatty } from 'tty';
12+
1213
const pkg = require('../package.json');
1314

1415
function fatal(message: any, ...args: any[]): void {
@@ -281,8 +282,10 @@ module.exports = function (argv: string[]): void {
281282
program
282283
.command('search <text>')
283284
.option('--json', 'Output result in json format', false)
285+
.option('--stats', 'Shows the extension rating and download counts', false)
286+
.option('-p, --pagesize [value]', 'Number of results to return', '100')
284287
.description('search extension gallery')
285-
.action((text, { json }) => main(search(text, json)));
288+
.action((text, { json, pagesize, stats }) => main(search(text, json, parseInt(pagesize), stats)));
286289

287290
program.on('command:*', ([cmd]: string) => {
288291
if (cmd === 'create-publisher') {

src/search.ts

+60-24
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,24 @@ import {
33
ExtensionQueryFilterType,
44
ExtensionQueryFlags,
55
PublishedExtension,
6+
ExtensionStatistic,
67
} from 'azure-devops-node-api/interfaces/GalleryInterfaces';
7-
import { tableView, wordTrim } from './viewutils';
8-
9-
const pageSize = 100;
8+
import { ratingStars, tableView, wordTrim } from './viewutils';
9+
import { ExtensionStatiticsMap } from './show';
1010
const installationTarget = 'Microsoft.VisualStudio.Code';
1111
const excludeFlags = '37888'; //Value to exclude un-published, locked or hidden extensions
1212

13+
const baseResultsTableHeaders = ['<ExtensionId>', '<Publisher>', '<Name>'];
14+
1315
interface VSCodePublishedExtension extends PublishedExtension {
1416
publisher: { displayName: string; publisherName: string };
1517
}
16-
17-
export async function search(searchText: string, json: boolean = false): Promise<any> {
18+
export async function search(
19+
searchText: string,
20+
json: boolean = false,
21+
pageSize: number = 10,
22+
stats: boolean = false
23+
): Promise<any> {
1824
const api = getPublicGalleryAPI();
1925
const results = (await api.extensionQuery({
2026
pageSize,
@@ -23,11 +29,25 @@ export async function search(searchText: string, json: boolean = false): Promise
2329
{ filterType: ExtensionQueryFilterType.InstallationTarget, value: installationTarget },
2430
{ filterType: ExtensionQueryFilterType.ExcludeWithFlags, value: excludeFlags },
2531
],
26-
flags: [ExtensionQueryFlags.ExcludeNonValidated, ExtensionQueryFlags.IncludeLatestVersionOnly],
32+
flags: [
33+
ExtensionQueryFlags.ExcludeNonValidated,
34+
ExtensionQueryFlags.IncludeLatestVersionOnly,
35+
stats ? ExtensionQueryFlags.IncludeStatistics : 0,
36+
],
2737
})) as VSCodePublishedExtension[];
2838

29-
if (json) {
30-
console.log(JSON.stringify(results, undefined, '\t'));
39+
if (stats || !json) {
40+
console.log(
41+
[
42+
`Search results:`,
43+
'',
44+
...buildResultTableView(results, stats),
45+
'',
46+
'For more information on an extension use "vsce show <extensionId>"',
47+
]
48+
.map(line => wordTrim(line.replace(/\s+$/g, '')))
49+
.join('\n')
50+
);
3151
return;
3252
}
3353

@@ -36,21 +56,37 @@ export async function search(searchText: string, json: boolean = false): Promise
3656
return;
3757
}
3858

39-
console.log(
40-
[
41-
`Search results:`,
42-
'',
43-
...tableView([
44-
['<ExtensionId>', '<Description>'],
45-
...results.map(({ publisher: { publisherName }, extensionName, shortDescription }) => [
46-
publisherName + '.' + extensionName,
47-
(shortDescription || '').replace(/\n|\r|\t/g, ' '),
48-
]),
49-
]),
50-
'',
51-
'For more information on an extension use "vsce show <extensionId>"',
52-
]
53-
.map(line => wordTrim(line.replace(/\s+$/g, '')))
54-
.join('\n')
59+
if (json) {
60+
console.log(JSON.stringify(results, undefined, '\t'));
61+
return;
62+
}
63+
}
64+
65+
function buildResultTableView(results: VSCodePublishedExtension[], stats: boolean): string[] {
66+
const values = results.map(({ publisher, extensionName, displayName, shortDescription, statistics }) => [
67+
publisher.publisherName + '.' + extensionName,
68+
publisher.displayName,
69+
wordTrim(displayName || '', 25),
70+
stats ? buildExtensionStatisticsText(statistics!) : wordTrim(shortDescription || '', 150).replace(/\n|\r|\t/g, ' '),
71+
]);
72+
73+
var resultsTableHeaders = stats
74+
? [...baseResultsTableHeaders, '<Installs>', '<Rating>']
75+
: [...baseResultsTableHeaders, '<Description>'];
76+
77+
const resultsTable = tableView([resultsTableHeaders, ...values]);
78+
79+
return resultsTable;
80+
}
81+
82+
function buildExtensionStatisticsText(statistics: ExtensionStatistic[]): string {
83+
const { install: installs = 0, averagerating = 0, ratingcount = 0 } = statistics?.reduce(
84+
(map, { statisticName, value }) => ({ ...map, [statisticName!]: value }),
85+
<ExtensionStatiticsMap>{}
86+
);
87+
88+
return (
89+
`${Number(installs).toLocaleString('en-US').padStart(12, ' ')} \t\t` +
90+
` ${ratingStars(averagerating).padEnd(3, ' ')} (${ratingcount})`
5591
);
5692
}

0 commit comments

Comments
 (0)