2023-08-02 22:56:08 +00:00
|
|
|
/** @module mwRestApiSearchClient */
|
|
|
|
|
|
|
|
const fetchJson = require( '../fetch.js' );
|
|
|
|
const urlGenerator = require( '../urlGenerator.js' );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {Object} RestResponse
|
|
|
|
* @property {RestResult[]} pages
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {Object} RestResult
|
|
|
|
* @property {number} id
|
|
|
|
* @property {string} key
|
|
|
|
* @property {string} title
|
|
|
|
* @property {string | null } matched_title
|
|
|
|
* @property {string} [description]
|
|
|
|
* @property {RestThumbnail | null} [thumbnail]
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {Object} RestThumbnail
|
|
|
|
* @property {string} url
|
|
|
|
* @property {number | null} [width]
|
|
|
|
* @property {number | null} [height]
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {Object} SearchResponse
|
|
|
|
* @property {string} query
|
|
|
|
* @property {SearchResult[]} results
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {MwMap} config
|
|
|
|
* @param {string} query
|
|
|
|
* @param {Object} response
|
|
|
|
* @param {boolean} showDescription
|
|
|
|
* @return {SearchResponse}
|
|
|
|
*/
|
|
|
|
function adaptApiResponse( config, query, response, showDescription ) {
|
|
|
|
const urlGeneratorInstance = urlGenerator( config );
|
|
|
|
return {
|
|
|
|
query,
|
|
|
|
results: response.pages.map( ( page ) => {
|
|
|
|
const thumbnail = page.thumbnail;
|
|
|
|
return {
|
|
|
|
id: page.id,
|
2023-08-04 01:01:21 +00:00
|
|
|
label: page.matched_title || page.title,
|
2023-08-02 22:56:08 +00:00
|
|
|
key: page.key,
|
|
|
|
title: page.title,
|
|
|
|
description: showDescription ? page.description : undefined,
|
|
|
|
url: urlGeneratorInstance.generateUrl( page ),
|
|
|
|
thumbnail: thumbnail ? {
|
|
|
|
url: thumbnail.url,
|
|
|
|
width: thumbnail.width ?? undefined,
|
|
|
|
height: 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.
|
|
|
|
* @return {AbortableSearchFetch}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @callback loadMore
|
|
|
|
* @param {string} query The search term.
|
|
|
|
* @param {number} offset The number of search results that were already loaded.
|
|
|
|
* @param {number} [limit] How many further search results to load (at most).
|
|
|
|
* @return {AbortableSearchFetch}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {Object} SearchClient
|
|
|
|
* @property {fetchByTitle} fetchByTitle
|
|
|
|
* @property {loadMore} [loadMore]
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {MwMap} config
|
|
|
|
* @return {SearchClient}
|
|
|
|
*/
|
|
|
|
function mwRestApiSearchClient( config ) {
|
|
|
|
return {
|
|
|
|
/**
|
|
|
|
* @type {fetchByTitle}
|
|
|
|
*/
|
|
|
|
fetchByTitle: ( q, limit = config.wgCitizenMaxSearchResults, showDescription = true ) => {
|
|
|
|
const searchApiUrl = config.wgScriptPath + '/rest.php';
|
|
|
|
const params = { q, limit: limit.toString() };
|
|
|
|
const search = new URLSearchParams( params );
|
2024-01-27 02:50:21 +00:00
|
|
|
const url = `${searchApiUrl}/v1/search/title?${search.toString()}`;
|
2023-08-02 22:56:08 +00:00
|
|
|
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 = mwRestApiSearchClient;
|