The SearchClient library makes it easy to hook up your search-UI to a Haive SearchManager instance (see the app-search features of Haive App Search here).
Note: in v2+ the package namespace is Haive (instead of IntelliSearch)
The package handles all the backend web-services so that you can focus on the user interface instead.
The SearchClient wraps and manages all the Haive SearchManager REST web-services:
In addition, it also handles a OpenID authentication.
For projects that consumes npm packages natively you add this package as you would add any other npm-package:
> npm install --save search-client
Since we have implemented the search-client in Typescript all the data-types and signatures are available for your IDE to use as intellisense. Please also use the documentation available in the generated API-documentation in the search-client doc-folder (typically ./node_modules/search-client/doc/index.html).
For web-pages that needs to have a script-tag embedded you can fetch the file(s) needed via the jsDelivr cdn, like this:
<script src="//cdn.jsdelivr.net/npm/search-client@{version}/dist/Haive.min.js"></script>
- where {version}
is to be replaced with the actual version you want.
CDN version aliases:
We strongly recommend that you use the full version id for production sites. For development sites we do recommend the same, but we also see that using a version alias might be handy in some cases.
latest
You can use the jsdelivr version alias latest
to always just get the latest version. Just be warned that your site is at high risk of breaking when new versions of the search-client are released. If the search-client library is updated and somehow is no longer compatible with your code, then your site will potentially break and stop working.
<Major>
(i.e. 1
)
This means that it will get the latest version for the given major version. Note that the same warning as for latest
applies, although this is less risky than just getting any latest
version.
<Major.Minor>
(i.e. 1.1
)
This means that it will get the latest version for the given major.minor version. Note that the same warning as for latest
applies, although this is less risky than both of the above options.
Note: You can replace dist
with es
to get different builds of the library too. For browser script you should use dist
as that version is in UMD format.
A benefit to using the npm system is the inclusion of map
-files. These are available for the es
and lib
versions only. Next to the browser-bundles in the project you can find accompanying .map
files that browsers are able to utilize in order to give a better debugging experience.
This section will cover only the basics. We highly recommend using the API-documentation for more details and insight.
The two central classes are SearchClient and Settings:
The central class is the SearchClient. To start using it you will need to create a new instance of it.
Note: If you are embedding the library via a script-tag then all the library features are in the Haive namespace.
The constructor takes one parameter (settings
: ISettings), where at least the Settings.baseUrl must be set.
The settings interface has properties that help you customize the solution to your needs. The baseUrl
is typically "http://<your-server>:9950"
for the Haive SearchManager.
We recommend using the automatic mode, where you only need to interface with the SearchClient class and it's settings.
The Settings class has the following properties:
baseUrl
: string - The base url for the endpoint (domain + port only).basePath
: string - The path (default usually is correct: "RestService/v4)"
authentication
: AuthenticationSettings - Defines how authentication
-calls are handledautocomplete
: AutocompleteSettings - Defines how autocomplete
-calls are handledcategorize
: CategorizeSettings - Defines how categorize
-calls are handledfind
: FindSettings - Defines how find
-calls are handledquery
: Query - Defines the default query-options.\Please consult the documentation for specific details on each of them. Suffice to say that all the *Settings
classes contains a boolean property called enabled
, which by default is true
.
The automatic mode is by far the simplest and sexiest way for you as a developer to use the search-client. It makes it very easy for you to hook up your search-ui to the search-backend, without you having to add source code to detect when and how the various features are to be executed. Instead you can "stand on our shoulders" and leverage the knowledge that is already incorporated into the implemented automated triggers. You can set things up and it should "just work". We do however suggest that you invest time into understanding the various search-features and how the the triggers work. That will help you find the best way to implement the search-backend for your needs.
The Autocomplete
, Categorize
, Find
(and optionally also the authentication
) services are all essential parts of the automatic mode. Because of this their respective settings objects also contain a property called trigger
:
We suggest spending time on examining the triggers for the respective services above.
The automatic mode operations (autocomplete, categorize and find) also allow you to specify callbacks as a part of the configuration. The callbacks can be used in the manual mode too, but they were designed to be part of the automatic mode primarily.
cbRequest
This callback is called before the request is started. Typically you will use this to control loading/waiting indicators on the page. The signature includes some optional params (url: string, reqInit: RequestInit): bool
.
Note that if you add this callback, and explicitly return false, then the request will not be executed.
If you don't return or return false then the request runs as expected.
cbSuccess
This callback is called whenever a backend operation has completed and results have been received. The signature of the callback should be (data: <TDataType>) => void
, where the <TDataType> is string[]
for the autocomplete call, ICategories
for the categorize call and IMatches
for the find call.
cbError
This callback is called whenever a backend operation somehow fails to complete. The signature of the callback should be (error: any) => void
. The error object could be anything, but should explain the cause of the problem if console.log()'ed or toString()'ed to the page.
It is important to understand that Authentication, Autocomplete, Categorize and Find all have independent callbacks in the configuration. Because of this the success, error and busy-state for each of them can be tracked independently. This means that the query-field may have an indicator somewhere that indicates that it is doing a lookup (if wanted). The categories section may have an indicator to tell that it is working, and finally the results area may also have an indicator telling that results are pending.
In order for the automatic mode to work you need to update the values in your query-field as well as filters and/or sorting order / search-type. This is how the search-client will know when to execute searches/lookups and not.
These are the properties on the SearchClient class that you can manipulate in order to change the query that the search-client is to execute. It is expected that you both set
and get
them directly:
clientId
: stringdateFrom
: DateSpecificationdateTo
: DateSpecificationfilters
: string[]matchGenerateContent
: booleanmatchGenerateContentHighlights
: booleanmatchGrouping
: booleanmatchOrderBy
: OrderBymatchPage
: numbermatchPageSize
: numbermaxSuggestions
: numberquery
: QueryqueryText
: stringsearchType
: SearchTypeuiLanguageCode
: stringI.e. searchClient.queryText = "my query";
The normal thing to do is to wire the UI events so that when the user changes the content of the query input field you immediately update the queryText
property.
In addition the there are some additional methods that help manage changes in the UI:
toggleCategoryExpansion(...)
SearchClient.toggleCategoryExpansion - To toggle expanded/collapsed state for a category in the category-tree.filterAdd(...)
SearchClient.filterAdd - To add a category as a filterfilterRemove(...)
SearchClient.filterRemove - To remove a category as a filterfilterToggle(...)
SearchClient.filterToggle - To toggle a category as a filterisFilter(...)
SearchClient.isFilter - To check whether a given category-node is also a filterhasChildFilter()
SearchClient.hasChildFilter - To check whether any child of a given category-node is a filtermatchPageNext()
SearchClient.matchPageNext - To go to the next page of matchesmatchPagePrev()
SearchClient.matchPagePrev - To fgo back to the previous page of matchesupdate(...)
SearchClient.update - Typically called when the user clicks the search-button (or when i.e. the Enter-button has been pressed in the query-field). Will update the services according to changes in the query object (if any).forceUpdate(...)
SearchClient.forceUpdate - Used to force an update - even if there has been no changes in the query.reset()
SearchClient.reset - Resets the search-client instance back to the original startup state (handy to reset filters, query++)Please note that any of the services' registered callbacks will be called as a part of the fetch-process. This regards to both automatic and manual mode fetches. If you don't want the callbacks to be enabled you have two options:
deferUpdates(true)
before you do anything that would normally trigger callbacks. This will in turn call deferUpdates(true)
for all services. When you want callbacks to again be activated, call deferUpdate(false)
method. When first param is false it optionally takes a second parameter that can be used to indicate whether pending updates are to be skipped or not.deferUpdates(true)
before you do anything that would normally trigger callbacks. And then afterwards, if you want the callbacks to again be active, call deferUpdates(false)
and use the second parameter to indicate whether pending updates are to be skipped or not.Please see SearchClient.deferUpdates for more information.
The Haive SearchManager supports two modes of authentication:
Both modes are described in details below. If the index is public and does not use authentication then you can turn off authentication (which is enabled by default) by passing this in the settings object in the SearchClient constructor: authentication: { enabled: false }
.
The Haive SearchManager supports JWT based (JSON Web Token) authentication for differentiating users/permissions. To use this kind of authentication:
The SearchManager must be configured to use the CurrentPrincipal
plugin (which then extracts the authentication JWT package).
A web-service that identifies the user must be setup that is accessible from the page that the search-client runs on.
The SearchClient authentication settings object must define:
{ user: { jwt: "actualtokenhash" } }
then the tokenPath should be [ "user", "jwt" ]
.The authentication system, when enabled will attempt to fetch the authentication-token as soon as it is setup (trying to pre-fetch it to have it ready asap in case a search is made).
The authentication system decodes the jwt-token when received and checks for when the token expires. It then sets up a timeout to fetch a new token in ample time before the current one expires. The overlap for this is defined in its triggers: authentication: { triggers: { expiryOverlap: 60 } }
. The default is 60 seconds, which means that the client will try to get a new JWT 60 seconds before the old one expires.
Example:
"authentication": { "type": "jwt", "baseUrl": "auth_webservice_url", "servicePath": "auth/login", "enabled": true }
The Haive SearchManager supports OpenId Connect based authentication.
The SearchManager must be configured to use the CurrentPrincipal
plugin (which then extracts the authentication JWT package).
A web-service that identifies the user must be setup that is accessible from the page that the search-client runs on.
The SearchClient authentication settings object must define:
Implicit flow example:
"authentication": { "type": "oidc", "baseUrl": "localhost:5000", "silentRedirectUri": "localhost:9000/silent.html", "redirectUri": "localhost:9000/callback.html", "postLogoutRedirectUri": "localhost:9000", "servicePath": "", "clientId": "haive.webclient.implicit", "scope": "openid profile", "responseType": "id_token token", "responseMode": "fragment", "enabled": true, "enableLogging": true }
Authorization code flow example:
"authentication": { "type": "oidc", "baseUrl": "localhost:5000", "silentRedirectUri": "localhost:9000/silent.html", "redirectUri": "localhost:9000/callback.html", "postLogoutRedirectUri": "localhost:9000", "servicePath": "", "clientId": "haive.webclient.implicit", "scope": "openid profile", "responseType": "id_token token", "responseMode": "query", "enabled": true, "enableLogging": true }
Example configuration is provided in samples\plain\cfg\search-settings-oidc.js config file.
If you are using typescript, then the data-types are available for your IDE to use. If not, then all types and definitions are available in the generated API-documentation in the search-client docs-folder (typically ./node_modules/search-client/docs/index.html
).
Generated using TypeDoc