diff --git a/dev-packages/ovsx-client/src/ovsx-client.ts b/dev-packages/ovsx-client/src/ovsx-client.ts index 685316a6bcd46..f79dacf8f9532 100644 --- a/dev-packages/ovsx-client/src/ovsx-client.ts +++ b/dev-packages/ovsx-client/src/ovsx-client.ts @@ -34,6 +34,10 @@ export interface OVSXClientOptions { apiVersion: string apiUrl: string } + +export const OVSXClientProvider = Symbol('OVSXClientProvider'); +export type OVSXClientProvider = () => Promise; + export class OVSXClient { constructor(readonly options: OVSXClientOptions) { } diff --git a/packages/vsx-registry/src/browser/ovsx-async-client.ts b/packages/vsx-registry/src/browser/ovsx-async-client.ts deleted file mode 100644 index 56871769e873d..0000000000000 --- a/packages/vsx-registry/src/browser/ovsx-async-client.ts +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************** - * Copyright (C) 2021 Ericsson and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License v. 2.0 are satisfied: GNU General Public License, version 2 - * with the GNU Classpath Exception which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - ********************************************************************************/ - -import { OVSXClient, OVSXClientOptions } from '@theia/ovsx-client/lib'; - -/** - * In some instances, the OVSXClient must be created asynchronously. This class - * makes it possible to get an un-initialized instance and wait for it to be ready. - */ -export class OVSXAsyncClient extends OVSXClient { - - /** - * Resolves once the initial asynchronous options are resolved. - * - * Calling methods before this promise is resolved will throw errors. - */ - readonly ready: Promise; - - constructor(asyncOptions: Promise) { - super(undefined!); // hack: using methods at this point will fail. - this.ready = asyncOptions.then(options => { - (this.options as OVSXClientOptions) = options; - return this; - }); - } -} diff --git a/packages/vsx-registry/src/browser/vsx-extensions-model.ts b/packages/vsx-registry/src/browser/vsx-extensions-model.ts index ba611fdc387f7..95fcc4c997e26 100644 --- a/packages/vsx-registry/src/browser/vsx-extensions-model.ts +++ b/packages/vsx-registry/src/browser/vsx-extensions-model.ts @@ -30,7 +30,7 @@ import { WorkspaceService } from '@theia/workspace/lib/browser'; import { RecommendedExtensions } from './recommended-extensions/recommended-extensions-preference-contribution'; import URI from '@theia/core/lib/common/uri'; import { VSXResponseError, VSXSearchParam } from '@theia/ovsx-client/lib/ovsx-types'; -import { OVSXAsyncClient } from './ovsx-async-client'; +import { OVSXClientProvider } from '@theia/ovsx-client'; @injectable() export class VSXExtensionsModel { @@ -38,8 +38,8 @@ export class VSXExtensionsModel { protected readonly onDidChangeEmitter = new Emitter(); readonly onDidChange = this.onDidChangeEmitter.event; - @inject(OVSXAsyncClient) - protected client: OVSXAsyncClient; + @inject(OVSXClientProvider) + protected clientProvider: OVSXClientProvider; @inject(HostedPluginSupport) protected readonly pluginSupport: HostedPluginSupport; @@ -63,7 +63,6 @@ export class VSXExtensionsModel { @postConstruct() protected async init(): Promise { - await this.client.ready; await Promise.all([ this.initInstalled(), this.initSearchResult(), @@ -167,14 +166,15 @@ export class VSXExtensionsModel { }, 150); protected doUpdateSearchResult(param: VSXSearchParam, token: CancellationToken): Promise { return this.doChange(async () => { - const result = await this.client.search(param); + const client = await this.clientProvider(); + const result = await client.search(param); if (token.isCancellationRequested) { return; } const searchResult = new Set(); for (const data of result.extensions) { const id = data.namespace.toLowerCase() + '.' + data.name.toLowerCase(); - const extension = this.client.getLatestCompatibleVersion(data); + const extension = client.getLatestCompatibleVersion(data); if (!extension) { continue; } @@ -260,7 +260,8 @@ export class VSXExtensionsModel { } if (extension.readmeUrl) { try { - const rawReadme = await this.client.fetchText(extension.readmeUrl); + const client = await this.clientProvider(); + const rawReadme = await client.fetchText(extension.readmeUrl); const readme = this.compileReadme(rawReadme); extension.update({ readme }); } catch (e) { @@ -292,7 +293,8 @@ export class VSXExtensionsModel { if (!this.shouldRefresh(extension)) { return extension; } - const data = await this.client.getLatestCompatibleExtensionVersion(id); + const client = await this.clientProvider(); + const data = await client.getLatestCompatibleExtensionVersion(id); if (!data) { return; } diff --git a/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts b/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts index 300de4549dbb7..56c5c253dfbd8 100644 --- a/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts +++ b/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts @@ -32,20 +32,17 @@ import { VSXEnvironment } from '../common/vsx-environment'; import { VSXExtensionsSearchModel } from './vsx-extensions-search-model'; import { bindExtensionPreferences } from './recommended-extensions/recommended-extensions-preference-contribution'; import { bindPreferenceProviderOverrides } from './recommended-extensions/preference-provider-overrides'; -import { OVSXAsyncClient } from './ovsx-async-client'; +import { OVSXClient, OVSXClientProvider } from '@theia/ovsx-client'; export default new ContainerModule((bind, unbind) => { bind(VSXEnvironment).toSelf().inSingletonScope(); - bind(OVSXAsyncClient).toDynamicValue(ctx => { + bind(OVSXClientProvider).toProvider(ctx => () => new Promise(async resolve => { const vsxEnvironment = ctx.container.get(VSXEnvironment); - return new OVSXAsyncClient(Promise.all([ - vsxEnvironment.getVscodeApiVersion(), - vsxEnvironment.getRegistryApiUri() - ]).then(([apiVersion, apiUri]) => ({ - apiVersion, - apiUrl: apiUri.toString() - }))); - }).inSingletonScope(); + const apiVersion = await vsxEnvironment.getVscodeApiVersion(); + const apiUrl = (await vsxEnvironment.getRegistryApiUri()).toString(); + const client: OVSXClient = new OVSXClient({ apiVersion, apiUrl }); + resolve(client); + })); bind(VSXExtension).toSelf(); bind(VSXExtensionFactory).toFactory(ctx => (option: VSXExtensionOptions) => { diff --git a/packages/vsx-registry/src/node/vsx-extension-resolver.ts b/packages/vsx-registry/src/node/vsx-extension-resolver.ts index 029afe1470078..61865b0c18c5a 100644 --- a/packages/vsx-registry/src/node/vsx-extension-resolver.ts +++ b/packages/vsx-registry/src/node/vsx-extension-resolver.ts @@ -23,13 +23,13 @@ import { injectable, inject } from '@theia/core/shared/inversify'; import URI from '@theia/core/lib/common/uri'; import { PluginDeployerResolver, PluginDeployerResolverContext } from '@theia/plugin-ext/lib/common/plugin-protocol'; import { VSXExtensionUri } from '../common/vsx-extension-uri'; -import { OVSXClient } from '@theia/ovsx-client/lib/ovsx-client'; +import { OVSXClientProvider } from '@theia/ovsx-client'; @injectable() export class VSXExtensionResolver implements PluginDeployerResolver { - @inject(OVSXClient) - protected client: OVSXClient; + @inject(OVSXClientProvider) + protected clientProvider: OVSXClientProvider; protected readonly downloadPath: string; @@ -49,7 +49,8 @@ export class VSXExtensionResolver implements PluginDeployerResolver { return; } console.log(`[${id}]: trying to resolve latest version...`); - const extension = await this.client.getLatestCompatibleExtensionVersion(id); + const client = await this.clientProvider(); + const extension = await client.getLatestCompatibleExtensionVersion(id); if (!extension) { return; } diff --git a/packages/vsx-registry/src/node/vsx-registry-backend-module.ts b/packages/vsx-registry/src/node/vsx-registry-backend-module.ts index cbb4a41f767f5..4a2bde4afd705 100644 --- a/packages/vsx-registry/src/node/vsx-registry-backend-module.ts +++ b/packages/vsx-registry/src/node/vsx-registry-backend-module.ts @@ -17,18 +17,19 @@ import { ContainerModule } from '@theia/core/shared/inversify'; import { VSXExtensionResolver } from './vsx-extension-resolver'; import { PluginDeployerResolver } from '@theia/plugin-ext/lib/common/plugin-protocol'; -import { VSCODE_DEFAULT_API_VERSION, VSX_REGISTRY_URL_DEFAULT } from '@theia/plugin-ext-vscode/lib/common/plugin-vscode-types'; import { OVSXClient } from '@theia/ovsx-client/lib/ovsx-client'; +import { OVSXClientProvider } from '@theia/ovsx-client'; +import { VSXEnvironment } from '../common/vsx-environment'; export default new ContainerModule(bind => { - bind(OVSXClient).toConstantValue(new OVSXClient({ - apiVersion: process.env['VSCODE_API_VERSION'] || VSCODE_DEFAULT_API_VERSION, - apiUrl: resolveRegistryUrl() + bind(VSXEnvironment).toSelf().inSingletonScope(); + bind(OVSXClientProvider).toProvider(ctx => () => new Promise(async resolve => { + const vsxEnvironment = ctx.container.get(VSXEnvironment); + const apiVersion = await vsxEnvironment.getVscodeApiVersion(); + const apiUrl = (await vsxEnvironment.getRegistryApiUri()).toString(); + const client: OVSXClient = new OVSXClient({ apiVersion, apiUrl }); + resolve(client); })); bind(VSXExtensionResolver).toSelf().inSingletonScope(); bind(PluginDeployerResolver).toService(VSXExtensionResolver); }); - -function resolveRegistryUrl(): string { - return process.env['VSX_REGISTRY_URL'] || VSX_REGISTRY_URL_DEFAULT; -}