diff --git a/assets/js/autocomplete/client.ts b/assets/js/autocomplete/client.ts new file mode 100644 index 00000000..43fea48c --- /dev/null +++ b/assets/js/autocomplete/client.ts @@ -0,0 +1,73 @@ +import { HttpClient } from '../utils/http-client.ts'; + +export interface TagSuggestion { + /** + * If present, then this suggestion is for a tag alias. + * If absent, then this suggestion is for the `canonical` tag name. + */ + alias?: null | string; + + /** + * The canonical name of the tag (non-alias). + */ + canonical: string; + + /** + * Number of images tagged with this tag. + */ + images: number; +} + +export interface GetTagSuggestionsResponse { + suggestions: TagSuggestion[]; +} + +export interface GetTagSuggestionsRequest { + /** + * Term to complete. + */ + term: string; + + /** + * Maximum number of suggestions to return. + */ + limit: number; +} + +/** + * Autocomplete API client for Philomena backend. + */ +export class AutocompleteClient { + private http: HttpClient = new HttpClient(); + + /** + * Fetches server-side tag suggestions for the given term. The provided incomplete + * term is expected to be normalized by the caller (i.e. lowercased and trimmed). + * This is because the caller is responsible for caching the normalized term. + */ + async getTagSuggestions(request: GetTagSuggestionsRequest): Promise { + return this.http.fetchJson('/autocomplete/tags', { + query: { + vsn: '2', + term: request.term, + limit: request.limit.toString(), + }, + }); + } + + /** + * Issues a GET request to fetch the compiled autocomplete index. + */ + async getCompiledAutocomplete(): Promise { + const now = new Date(); + const key = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDate()}`; + + const response = await this.http.fetch(`/autocomplete/compiled`, { + query: { vsn: '2', key }, + credentials: 'omit', + cache: 'force-cache', + }); + + return response.arrayBuffer(); + } +}