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/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..41433cc97c335 100644 --- a/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts +++ b/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts @@ -28,24 +28,13 @@ import { VSXExtensionFactory, VSXExtension, VSXExtensionOptions } from './vsx-ex import { VSXExtensionEditor } from './vsx-extension-editor'; import { VSXExtensionEditorManager } from './vsx-extension-editor-manager'; import { VSXExtensionsSourceOptions } from './vsx-extensions-source'; -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 { bindOVSXClientProvider } from '../common/ovsx-client-provider'; export default new ContainerModule((bind, unbind) => { - bind(VSXEnvironment).toSelf().inSingletonScope(); - bind(OVSXAsyncClient).toDynamicValue(ctx => { - const vsxEnvironment = ctx.container.get(VSXEnvironment); - return new OVSXAsyncClient(Promise.all([ - vsxEnvironment.getVscodeApiVersion(), - vsxEnvironment.getRegistryApiUri() - ]).then(([apiVersion, apiUri]) => ({ - apiVersion, - apiUrl: apiUri.toString() - }))); - }).inSingletonScope(); + bindOVSXClientProvider(bind); bind(VSXExtension).toSelf(); bind(VSXExtensionFactory).toFactory(ctx => (option: VSXExtensionOptions) => { diff --git a/packages/vsx-registry/src/browser/ovsx-async-client.ts b/packages/vsx-registry/src/common/ovsx-client-provider.ts similarity index 51% rename from packages/vsx-registry/src/browser/ovsx-async-client.ts rename to packages/vsx-registry/src/common/ovsx-client-provider.ts index 56871769e873d..00a5b02908fbc 100644 --- a/packages/vsx-registry/src/browser/ovsx-async-client.ts +++ b/packages/vsx-registry/src/common/ovsx-client-provider.ts @@ -14,26 +14,18 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { OVSXClient, OVSXClientOptions } from '@theia/ovsx-client/lib'; +import { interfaces } from '@theia/core/shared/inversify'; +import { OVSXClient, OVSXClientProvider } from '@theia/ovsx-client'; +import { VSXEnvironment } from './vsx-environment'; -/** - * 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; - }); - } +export function bindOVSXClientProvider(bind: interfaces.Bind): void { + bind(VSXEnvironment).toSelf().inSingletonScope(); + bind(OVSXClientProvider).toProvider(ctx => async () => { + const vsxEnvironment = ctx.container.get(VSXEnvironment); + const [apiVersion, apiUrl] = await Promise.all([ + vsxEnvironment.getVscodeApiVersion(), + vsxEnvironment.getRegistryApiUri() + ]); + return new OVSXClient({ apiVersion, apiUrl: apiUrl.toString() }); + }); } 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..af61e55ae7181 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,10 @@ 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 { bindOVSXClientProvider } from '../common/ovsx-client-provider'; export default new ContainerModule(bind => { - bind(OVSXClient).toConstantValue(new OVSXClient({ - apiVersion: process.env['VSCODE_API_VERSION'] || VSCODE_DEFAULT_API_VERSION, - apiUrl: resolveRegistryUrl() - })); + bindOVSXClientProvider(bind); bind(VSXExtensionResolver).toSelf().inSingletonScope(); bind(PluginDeployerResolver).toService(VSXExtensionResolver); }); - -function resolveRegistryUrl(): string { - return process.env['VSX_REGISTRY_URL'] || VSX_REGISTRY_URL_DEFAULT; -}