Skip to content

Commit

Permalink
vsx: fix search query
Browse files Browse the repository at this point in the history
The following commit fixes the `open-vsx` search query:
- fixes the `search` query when multiple search parameters are used.
- adds a test to verify the search query.
- adds support for additional search parameters (`sortOrder`, `sortBy`,
  and `includeAllVersions`).

Signed-off-by: vince-fugnitto <[email protected]>
  • Loading branch information
vince-fugnitto committed Oct 8, 2020
1 parent d262753 commit fd7d9d2
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 9 deletions.
83 changes: 83 additions & 0 deletions packages/vsx-registry/src/common/vsx-registry-api.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/********************************************************************************
* Copyright (C) 2020 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 * as chai from 'chai';
import { Container } from 'inversify';
import { VSXRegistryAPI } from './vsx-registry-api';
import URI from '@theia/core/lib/common/uri';
import { VSXEnvironment } from './vsx-environment';
import { VSXSearchParam } from './vsx-registry-types';

const expect = chai.expect;

describe('VSX Registry API', () => {

let api: VSXRegistryAPI;

beforeEach(() => {
const container = new Container();
container.bind(VSXRegistryAPI).toSelf().inSingletonScope();
container.bind(VSXEnvironment).toConstantValue(<VSXEnvironment>{
async getRegistryApiUri(): Promise<URI> {
return new URI('https://open-vsx.org/api');
},
async getRegistryUri(): Promise<URI> {
return new URI('https://open-vsx.org');
}
});
api = container.get<VSXRegistryAPI>(VSXRegistryAPI);
});

describe('#buildSearchUri', () => {

it('should correctly build the search URI with the single `query` parameter present', async () => {
const expected = 'https://open-vsx.org/api/-/search?query=javascript';
const param: VSXSearchParam = {
query: 'javascript',
};
const query = await api['buildSearchUri'](param);
expect(query).to.eq(expected);
});

it('should correctly build the search URI with the multiple search parameters present', async () => {
let expected = 'https://open-vsx.org/api/-/search?query=javascript&category=languages&size=20&offset=10&includeAllVersions=true';
let param: VSXSearchParam = {
query: 'javascript',
category: 'languages',
size: 20,
offset: 10,
includeAllVersions: true,
};
let query = await api['buildSearchUri'](param);
expect(query).to.eq(expected);

expected = 'https://open-vsx.org/api/-/search?query=javascript&category=languages&size=20&offset=10&sortOrder=desc&sortBy=relevance&includeAllVersions=true';
param = {
query: 'javascript',
category: 'languages',
size: 20,
offset: 10,
sortOrder: 'desc',
sortBy: 'relevance',
includeAllVersions: true
};
query = await api['buildSearchUri'](param);
expect(query).to.eq(expected);
});

});

});
30 changes: 22 additions & 8 deletions packages/vsx-registry/src/common/vsx-registry-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,41 @@ export class VSXRegistryAPI {
protected readonly environment: VSXEnvironment;

async search(param?: VSXSearchParam): Promise<VSXSearchResult> {
const searchUri = await this.buildSearchUri(param);
return this.fetchJson<VSXSearchResult>(searchUri);
}

protected async buildSearchUri(param?: VSXSearchParam): Promise<string> {
const apiUri = await this.environment.getRegistryApiUri();
let searchUri = apiUri.resolve('-/search').toString();
if (param) {
let query = '';
const query: string[] = [];
if (param.query) {
query += 'query=' + encodeURIComponent(param.query);
query.push('query=' + encodeURIComponent(param.query));
}
if (param.category) {
query += 'category=' + encodeURIComponent(param.category);
query.push('category=' + encodeURIComponent(param.category));
}
if (param.size) {
query += 'size=' + param.size;
query.push('size=' + param.size);
}
if (param.offset) {
query += 'offset=' + param.offset;
query.push('offset=' + param.offset);
}
if (param.sortOrder) {
query.push('sortOrder=' + encodeURIComponent(param.sortOrder));
}
if (query) {
searchUri += '?' + query;
if (param.sortBy) {
query.push('sortBy=' + encodeURIComponent(param.sortBy));
}
if (param.includeAllVersions) {
query.push('includeAllVersions=' + param.includeAllVersions);
}
if (query.length > 0) {
searchUri += '?' + query.join('&');
}
}
return this.fetchJson<VSXSearchResult>(searchUri);
return searchUri;
}

async getExtension(id: string): Promise<VSXExtensionRaw> {
Expand Down
30 changes: 29 additions & 1 deletion packages/vsx-registry/src/common/vsx-registry-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,41 @@
********************************************************************************/

/**
* Should be aligned with https://github.com/eclipse/openvsx/blob/793d0691258a6029e5ebb8cc8783b366b67d16ca/server/src/main/java/org/eclipse/openvsx/RegistryAPI.java#L192-L196
* The possible options when performing a search.
*
* For available options, and default values consult the `swagger`: https://open-vsx.org/swagger-ui/#/registry-api/searchUsingGET.
*
* Should be aligned with https://github.com/eclipse/openvsx/blob/b5694a712e07d266801394916bac30609e16d77b/server/src/main/java/org/eclipse/openvsx/RegistryAPI.java#L246-L266
*/
export interface VSXSearchParam {
/**
* The query text for searching.
*/
query?: string;
/**
* The extension category.
*/
category?: string;
/**
* The maximum number of entries to return.
*/
size?: number;
/**
* The number of entries to skip (usually a multiple of the page size).
*/
offset?: number;
/**
* The sort order.
*/
sortOrder?: 'asc' | 'desc';
/**
* The sort key.
*/
sortBy?: 'averageRating' | 'downloadCount' | 'relevance' | 'timestamp';
/**
* Determines whether to include information regarding all available entries for the entry.
*/
includeAllVersions?: boolean;
}

/**
Expand Down

0 comments on commit fd7d9d2

Please sign in to comment.