Skip to content

Commit d025f0e

Browse files
author
Akash Satheesan
committed
Allow use of multiple extension galleries
1 parent 28e98c0 commit d025f0e

File tree

4 files changed

+45
-30
lines changed

4 files changed

+45
-30
lines changed

lib/vscode/src/vs/platform/extensionManagement/common/extensionGalleryService.ts

+42-27
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
343343

344344
declare readonly _serviceBrand: undefined;
345345

346-
private extensionsGalleryUrl: string | undefined;
346+
private extensionsGalleryUrl: string[] | undefined;
347347
private extensionsControlUrl: string | undefined;
348348

349349
private readonly commonHeadersPromise: Promise<{ [key: string]: string; }>;
@@ -363,8 +363,13 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
363363
this.commonHeadersPromise = resolveMarketplaceHeaders(productService.version, this.environmentService, this.fileService, storageService);
364364
}
365365

366-
private api(path = ''): string {
367-
return `${this.extensionsGalleryUrl}${path}`;
366+
private api(path = ''): string[] {
367+
if (!!this.extensionsGalleryUrl) {
368+
return this.extensionsGalleryUrl?.map(
369+
(galleryUrl) => `${galleryUrl}${path}`
370+
)
371+
}
372+
return [];
368373
}
369374

370375
isEnabled(): boolean {
@@ -543,43 +548,53 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
543548
'Content-Length': String(data.length)
544549
};
545550

546-
const context = await this.requestService.request({
547-
type: 'POST',
548-
url: this.api('/extensionquery'),
549-
data,
550-
headers
551-
}, token);
551+
const galleryExtensions: IRawGalleryExtension[] = [];
552+
const seenExtensions: Set<String> = new Set();
552553

553-
if (context.res.statusCode && context.res.statusCode >= 400 && context.res.statusCode < 500) {
554-
return { galleryExtensions: [], total: 0 };
555-
}
554+
for (const url of this.api('/extensionquery')) {
555+
const context = await this.requestService.request({
556+
type: 'POST',
557+
url: url,
558+
data,
559+
headers
560+
}, token);
556561

557-
const result = await asJson<IRawGalleryQueryResult>(context);
558-
if (result) {
559-
const r = result.results[0];
560-
const galleryExtensions = r.extensions;
561-
const resultCount = r.resultMetadata && r.resultMetadata.filter(m => m.metadataType === 'ResultCount')[0];
562-
const total = resultCount && resultCount.metadataItems.filter(i => i.name === 'TotalCount')[0].count || 0;
562+
if (context.res.statusCode && context.res.statusCode >= 400 && context.res.statusCode < 500) {
563+
return { galleryExtensions: [], total: 0 };
564+
}
563565

564-
return { galleryExtensions, total };
566+
const result = await asJson<IRawGalleryQueryResult>(context);
567+
if (result) {
568+
const r = result.results[0];
569+
for (const extension of r.extensions) {
570+
if (!seenExtensions.has(extension.extensionId)) {
571+
galleryExtensions.push(extension);
572+
seenExtensions.add(extension.extensionId);
573+
}
574+
}
575+
}
565576
}
566-
return { galleryExtensions: [], total: 0 };
577+
return { galleryExtensions, total: galleryExtensions.length };
567578
}
568579

569580
async reportStatistic(publisher: string, name: string, version: string, type: StatisticType): Promise<void> {
581+
// TODO: investigate further - currently we just send stats everywhere
582+
// this is only used in one place - uninstall tracking - but
570583
if (!this.isEnabled()) {
571584
return undefined;
572585
}
573586

574587
const commonHeaders = await this.commonHeadersPromise;
575588
const headers = { ...commonHeaders, Accept: '*/*;api-version=4.0-preview.1' };
576-
try {
577-
await this.requestService.request({
578-
type: 'POST',
579-
url: this.api(`/publishers/${publisher}/extensions/${name}/${version}/stats?statType=${type}`),
580-
headers
581-
}, CancellationToken.None);
582-
} catch (error) { /* Ignore */ }
589+
for (const url of this.api(`/publishers/${publisher}/extensions/${name}/${version}/stats?statType=${type}`)) {
590+
try {
591+
await this.requestService.request({
592+
type: 'POST',
593+
url: url,
594+
headers
595+
}, CancellationToken.None);
596+
} catch (error) { /* Ignore */ }
597+
}
583598
}
584599

585600
async download(extension: IGalleryExtension, location: URI, operation: InstallOperation): Promise<void> {

lib/vscode/src/vs/platform/product/common/productService.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export interface IProductConfiguration {
6969
readonly experimentsUrl?: string;
7070

7171
readonly extensionsGallery?: {
72-
readonly serviceUrl: string;
72+
readonly serviceUrl: string[];
7373
readonly itemUrl: string;
7474
readonly controlUrl: string;
7575
readonly recommendationsUrl: string;

lib/vscode/src/vs/server/ipc.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export interface WorkbenchOptions {
125125
readonly productConfiguration: {
126126
codeServerVersion?: string;
127127
readonly extensionsGallery?: {
128-
readonly serviceUrl: string;
128+
readonly serviceUrl: string[];
129129
readonly itemUrl: string;
130130
readonly controlUrl: string;
131131
readonly recommendationsUrl: string;

lib/vscode/src/vs/server/node/marketplace.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ const extractTar = async (tarPath: string, targetPath: string, options: IExtract
160160
*/
161161
export const enableCustomMarketplace = (): void => {
162162
(<any>product).extensionsGallery = { // Use `any` to override readonly.
163-
serviceUrl: process.env.SERVICE_URL || 'https://extensions.coder.com/api',
163+
serviceUrl: process.env.SERVICE_URL ? [process.env.SERVICE_URL] : ['https://open-vsx.org/vscode/gallery', 'https://extensions.coder.com/api'],
164164
itemUrl: process.env.ITEM_URL || '',
165165
controlUrl: '',
166166
recommendationsUrl: '',

0 commit comments

Comments
 (0)