mediawiki-skins-Vector/resources/skins.vector.search/restSearchClient.js
Lucas Werkmeister 090500276d search: Don’t pass searchApiUrl into fetchByTitle()
Not all implementations will need this (e.g. the Wikibase search is
based on the Action API, not the REST API), so simplify App and move
this bit of complexity into the default search client instead.

As far as I can tell from MediaWiki code search [1] and Global Search
[2], nothing apart from Wikibase uses wgVectorSearchClient yet, so we
should be able to make this breaking change now.

[1]: https://codesearch.wmcloud.org/search/?q=wgVectorSearchClient
[2]: https://global-search.toolforge.org/?q=wgVectorSearchClient&namespaces=2%2C4%2C8&title=%28Gadgets-definition%7C.*%5C.js%29

Change-Id: I0d52e407c12b3fbf80cd36ed66c67da4cba9acbd
2022-11-25 15:00:16 +01:00

112 lines
2.6 KiB
JavaScript

/* global RestResult, SearchResult */
/** @module restSearchClient */
const fetchJson = require( './fetch.js' );
const urlGenerator = require( './urlGenerator.js' );
/**
* @typedef {Object} RestResponse
* @property {RestResult[]} pages
*/
/**
* @typedef {Object} SearchResponse
* @property {string} query
* @property {SearchResult[]} results
*/
/**
* Nullish coalescing operator (??) helper
*
* @param {any} a
* @param {any} b
* @return {any}
*/
function nullish( a, b ) {
return ( a !== null && a !== undefined ) ? a : b;
}
/**
* @param {MwMap} config
* @param {string} query
* @param {RestResponse} restResponse
* @param {boolean} showDescription
* @return {SearchResponse}
*/
function adaptApiResponse( config, query, restResponse, showDescription ) {
const urlGeneratorInstance = urlGenerator( config );
return {
query,
results: restResponse.pages.map( ( page, index ) => {
const thumbnail = page.thumbnail;
return {
id: page.id,
value: page.id || -( index + 1 ),
label: page.title,
key: page.key,
title: page.title,
description: showDescription ? page.description : undefined,
url: urlGeneratorInstance.generateUrl( page ),
thumbnail: thumbnail ? {
url: thumbnail.url,
width: nullish( thumbnail.width, undefined ),
height: nullish( thumbnail.height, undefined )
} : undefined
};
} )
};
}
/**
* @typedef {Object} AbortableSearchFetch
* @property {Promise<SearchResponse>} fetch
* @property {Function} abort
*/
/**
* @callback fetchByTitle
* @param {string} query The search term.
* @param {number} [limit] Maximum number of results.
* @param {boolean} [showDescription] Whether descriptions should be added to the results.
* @return {AbortableSearchFetch}
*/
/**
* @typedef {Object} SearchClient
* @property {fetchByTitle} fetchByTitle
*/
/**
* @param {MwMap} config
* @return {SearchClient}
*/
function restSearchClient( config ) {
return config.get( 'wgVectorSearchClient', {
/**
* @type {fetchByTitle}
*/
fetchByTitle: ( q, limit = 10, showDescription = true ) => {
const searchApiUrl = config.get( 'wgVectorSearchApiUrl',
config.get( 'wgScriptPath' ) + '/rest.php'
);
const params = { q, limit };
const url = searchApiUrl + '/v1/search/title?' + $.param( params );
const result = fetchJson( url, {
headers: {
accept: 'application/json'
}
} );
const searchResponsePromise = result.fetch
.then( ( /** @type {RestResponse} */ res ) => {
return adaptApiResponse( config, q, res, showDescription );
} );
return {
abort: result.abort,
fetch: searchResponsePromise
};
}
} );
}
module.exports = restSearchClient;