From 3826665bf9a08a35d06c1c5a87a3bd6f0b190958 Mon Sep 17 00:00:00 2001 From: Prashant Cholachagudda Date: Wed, 18 May 2022 19:01:22 +0530 Subject: [PATCH] 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 --- src/main.ts | 5 ++- src/search.ts | 84 ++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 64 insertions(+), 25 deletions(-) diff --git a/src/main.ts b/src/main.ts index bda152c7..c2924a35 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,6 +9,7 @@ import { getLatestVersion } from './npm'; import { CancellationToken, log } from './util'; import * as semver from 'semver'; import { isatty } from 'tty'; + const pkg = require('../package.json'); function fatal(message: any, ...args: any[]): void { @@ -281,8 +282,10 @@ module.exports = function (argv: string[]): void { program .command('search ') .option('--json', 'Output result in json format', false) + .option('--stats', 'Shows the extension rating and download counts', false) + .option('-p, --pagesize [value]', 'Number of results to return', '100') .description('search extension gallery') - .action((text, { json }) => main(search(text, json))); + .action((text, { json, pagesize, stats }) => main(search(text, json, parseInt(pagesize), stats))); program.on('command:*', ([cmd]: string) => { if (cmd === 'create-publisher') { diff --git a/src/search.ts b/src/search.ts index 8f8c6b83..21596dc7 100644 --- a/src/search.ts +++ b/src/search.ts @@ -3,18 +3,24 @@ import { ExtensionQueryFilterType, ExtensionQueryFlags, PublishedExtension, + ExtensionStatistic, } from 'azure-devops-node-api/interfaces/GalleryInterfaces'; -import { tableView, wordTrim } from './viewutils'; - -const pageSize = 100; +import { ratingStars, tableView, wordTrim } from './viewutils'; +import { ExtensionStatiticsMap } from './show'; const installationTarget = 'Microsoft.VisualStudio.Code'; const excludeFlags = '37888'; //Value to exclude un-published, locked or hidden extensions +const baseResultsTableHeaders = ['', '', '']; + interface VSCodePublishedExtension extends PublishedExtension { publisher: { displayName: string; publisherName: string }; } - -export async function search(searchText: string, json: boolean = false): Promise { +export async function search( + searchText: string, + json: boolean = false, + pageSize: number = 10, + stats: boolean = false +): Promise { const api = getPublicGalleryAPI(); const results = (await api.extensionQuery({ pageSize, @@ -23,11 +29,25 @@ export async function search(searchText: string, json: boolean = false): Promise { filterType: ExtensionQueryFilterType.InstallationTarget, value: installationTarget }, { filterType: ExtensionQueryFilterType.ExcludeWithFlags, value: excludeFlags }, ], - flags: [ExtensionQueryFlags.ExcludeNonValidated, ExtensionQueryFlags.IncludeLatestVersionOnly], + flags: [ + ExtensionQueryFlags.ExcludeNonValidated, + ExtensionQueryFlags.IncludeLatestVersionOnly, + stats ? ExtensionQueryFlags.IncludeStatistics : 0, + ], })) as VSCodePublishedExtension[]; - if (json) { - console.log(JSON.stringify(results, undefined, '\t')); + if (stats || !json) { + console.log( + [ + `Search results:`, + '', + ...buildResultTableView(results, stats), + '', + 'For more information on an extension use "vsce show "', + ] + .map(line => wordTrim(line.replace(/\s+$/g, ''))) + .join('\n') + ); return; } @@ -36,21 +56,37 @@ export async function search(searchText: string, json: boolean = false): Promise return; } - console.log( - [ - `Search results:`, - '', - ...tableView([ - ['', ''], - ...results.map(({ publisher: { publisherName }, extensionName, shortDescription }) => [ - publisherName + '.' + extensionName, - (shortDescription || '').replace(/\n|\r|\t/g, ' '), - ]), - ]), - '', - 'For more information on an extension use "vsce show "', - ] - .map(line => wordTrim(line.replace(/\s+$/g, ''))) - .join('\n') + if (json) { + console.log(JSON.stringify(results, undefined, '\t')); + return; + } +} + +function buildResultTableView(results: VSCodePublishedExtension[], stats: boolean): string[] { + const values = results.map(({ publisher, extensionName, displayName, shortDescription, statistics }) => [ + publisher.publisherName + '.' + extensionName, + publisher.displayName, + wordTrim(displayName || '', 25), + stats ? buildExtensionStatisticsText(statistics!) : wordTrim(shortDescription || '', 150).replace(/\n|\r|\t/g, ' '), + ]); + + var resultsTableHeaders = stats + ? [...baseResultsTableHeaders, '', ''] + : [...baseResultsTableHeaders, '']; + + const resultsTable = tableView([resultsTableHeaders, ...values]); + + return resultsTable; +} + +function buildExtensionStatisticsText(statistics: ExtensionStatistic[]): string { + const { install: installs = 0, averagerating = 0, ratingcount = 0 } = statistics?.reduce( + (map, { statisticName, value }) => ({ ...map, [statisticName!]: value }), + {} + ); + + return ( + `${Number(installs).toLocaleString('en-US').padStart(12, ' ')} \t\t` + + ` ${ratingStars(averagerating).padEnd(3, ' ')} (${ratingcount})` ); }