@indexea/scaffold-svelte
Version:
This is the scaffolding of Indexea search, on which you can adjust the typography and style of the search interface
164 lines (151 loc) • 4.72 kB
text/typescript
/***
* openapi of indexea
*/
import { v4 as uuidv4 } from 'uuid';
import { Configuration, WidgetsApi, SearchApi, SearchWidgetHotWordsScopeEnum, WidgetBean, SearchWord, AutoCompleteItem } from '@indexea/sdk'
/**
* A simple wrapper for the Indexea API
*/
export class Indexea {
_config: Configuration;
_widget: string;
accessToken: string;
searchApi: SearchApi;
widgetApi: WidgetsApi;
/**
* initialize an indexea api wrapper
* @param endpoint remote endpoint url, ex: `https://api.indexea.com/v1`
* @param widget widget identifier
*/
constructor(endpoint: string, accessToken: string, widget: string) {
this._widget = widget;
this.accessToken = accessToken;
this._config = new Configuration({
basePath: endpoint,
headers: { accept: 'application/json' },
accessToken: () => {
return accessToken
},
credentials: 'include',
middleware: [],
queryParamsStringify
});
this.searchApi = new SearchApi(this._config)
this.widgetApi = new WidgetsApi(this._config)
}
/**
* get widget detail
* @returns
*/
async widget(): Promise<WidgetBean> {
return this.widgetApi.widgetDetail({ ident: this._widget }).catch(rejectError)
}
/**
* execute search on widget
* @param query query id
* @param q search keyword
* @param params search parameters, generally, it is an aggregation parameter filter condition
* @param from
* @param size
* @returns
*/
async search(query: number, q: string, params: any, from: number, size: number): Promise<object> {
let args = { widget: this._widget, query, q, params, from, size, userid: getUserId(), xToken: this.accessToken };
return this.searchApi.searchWidgetSearch(args).catch(rejectError);
}
/**
* get hotwords of query
* @param query query id
* @param scope
* @param count
* @returns
*/
async hotwords(query: number, scope: SearchWidgetHotWordsScopeEnum, count: number): Promise<Array<SearchWord>> {
return this.searchApi
.searchWidgetHotWords({ widget: this._widget, query, scope, count, xToken: this.accessToken })
.catch(rejectError)
}
/**
* get auto complete items for search box
* @param query query id
* @param q search keyword
* @param size
* @returns
*/
async autocomplete(query: number, q: string, size: number): Promise<Array<AutoCompleteItem>> {
return this.searchApi.searchWidgetAutoComplete({ widget: this._widget, query, q, userid: getUserId(), size, xToken: this.accessToken })
.catch(rejectError)
}
/**
* call this method when use click on a search result item.
* @param actionId
* @param docId
* @returns
*/
async click(actionId: string, docId: string): Promise<boolean> {
return this.searchApi.searchClick({ widget: this._widget, actionId, docId, userid: getUserId(), xToken: this.accessToken })
}
}
/**
* The unique identifier of the visitor, which will be transmitted to the search service through the header
* @returns
*/
function getUserId() {
var userid: string = window.localStorage.getItem('idx_userid') || '';
if (!userid) {
userid = uuidv4(); //Date.now().toString(36) + Math.random().toString(36);
window.localStorage.setItem('idx_userid', userid);
}
return userid;
}
/**
* Object to url request parameters
* @param obj
* @returns
*/
function queryParamsStringify(obj: Record<string, any>): string {
return Object.entries(obj).filter(([key, value]) => key && value != undefined)
.map(([key, value]) => {
if (typeof value !== 'object') {
return joinKV(key, value)
}
if (Array.isArray(value)) {
// Array type, using multiple keys, such as a=1&a=2&a=3 becomes a=[1,2,3] during backend processing
return value.filter(v => v).map(v => joinKV(key, v)).join('&')
}
return queryParamsStringify(value)
})
.join('&')
}
/**
* Concatenate url request parameters
* @param key
* @param value
* @returns
*/
function joinKV(key: string, value: any) {
return encodeURIComponent(key) + '=' + encodeURIComponent(value);
}
/**
* global error handler
* @param {*} fn_reject
* @param {*} err
*/
function rejectError(err: any) {
try {
return err.response
.json()
.then((json: any) => Promise.reject(json))
.catch((e: { error: any; message: any; }) =>
Promise.reject({
error: e.error || err.status || 999,
message: e.message || err.statusText || 'Unknown error'
})
)
} catch (e) {
return Promise.reject({
error: err.error || err.status || 999,
message: err.message || err.statusText || 'Unknown error'
})
}
}