UNPKG

@openfin/search-api

Version:

A search API framework for OpenFin.

583 lines (582 loc) 18.9 kB
import type OpenFin from '@openfin/core'; import { RegistrationMetaInfo } from '@client/index'; export type { RegistrationMetaInfo }; /** * Create a topic. * If the OpenFin identity creating the topic is running in a platform, the search topic will be sandboxed to the platform. * In order to subscribe to a sandboxed search topic, the UUID of the platform must be specified explicitly or the subscribing OpenFin identity must be running in the platform. * @param req the topic create request. */ export declare const create: () => Promise<SearchTopic>; /** * Subscribe to an existing search topic. * @param req the subscribe request. */ export declare const subscribe: () => Promise<SearchTopicClient>; /** * Search API object that is injected in the window. */ export type SearchAPI = { create: typeof create; subscribe: typeof subscribe; }; /** * A response to a search from a search provider. */ export interface SearchProviderResponse { /** * The search provider that responded with the search results. */ provider: SearchProviderInfo; /** * If the search result succeeds for this provider, results of the search will be set. */ results?: SearchResult[]; /** * A context with custom data to pass through search */ context?: any; /** * If the search failed for this provider, error will be set. */ error?: Error; } /** * The search request. */ export interface SearchRequest { /** * The search query. */ query: string; /** * Additional custom context that can be used for searching. */ context?: any; /** * A list of search provider names to execute the search request against. */ targets?: string[]; } /** * A generator that returns search responses from all providers that have currently responded. * * More documentation on Javascript Generators can be found [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator). */ export type SearchProviderResponseGenerator = AsyncGenerator<SearchProviderResponse[], SearchProviderResponse[], SearchProviderResponse[]>; /** * Describes the state of the search response generator. */ export declare enum SearchProviderResponseGeneratorState { /** * The generator is in the process of fetching the initial set of results from search providers. */ Fetching = "fetching", /** * The generator has fetched all initial results, and is now waiting for search providers with * open {@link SearchListenerResponse} streams to push new or updated search results. */ Fetched = "fetched", /** * All open {@link SearchListenerResponse} streams have closed, completing the request. * In this state, the set of responses returned by `generator.next()` are final. */ Complete = "complete" } /** * Extended search provider response generator with additional properties about the search request. */ export interface SearchProviderResponseGeneratorExtended extends SearchProviderResponseGenerator { /** * The id of the search request. */ id: string; /** * The state of the search provider response generator. */ state: SearchProviderResponseGeneratorState; /** * Notifies all search providers related to this search request * that the search requester is no longer listening for new or updated search results. * @experimental */ close: () => void; } /** * Called when a remote OpenFin identity, such as a view, attempts to connect * to the search topic. * * Returning false will reject said request. * * ```js * const allowedHosts = ["www.company.com"]; * searchTopic.onSubscription(identity => { * const info = await fin.View.wrapSync(identity).getInfo(); * const url = new URL(info.url); * * return allowedHosts.includes(url.host); * }); * ``` */ export type SubscriptionListener = (identity: OpenFin.Identity) => Promise<boolean>; /** * Called when a remote OpenFin identity, such as a view, disconnects from a Search topic. */ export type DisconnectListener = (identity: OpenFin.Identity) => Promise<void>; /** * Called when search provider deregisters from SearchTopic */ export type DeregisterListener = () => void | Promise<void>; /** * Called when search provider registers to SearchTopic */ export type RegisterListener = () => void | Promise<void>; /** * The client returned from subscribing as a secondary node to a search topic, which is managed by a primary node. * Can be used to interact with a search topic. */ export interface SearchTopicClient { /** * Obtain information about all search providers listening in on the topic. */ getAllProviders(): Promise<SearchProviderInfo[]>; /** * Execute a search on the search topic. * * The generator returned by this function can be called multiple times, returning the current list of search provider responses. * As more search providers respond to the search request the returned list of responses will grow in length. * * When all the search providers have responded to the search request, the generator will return the final * set of search response under the `value` attribute and set the 'done' attribute set to true. * * If no targets are included in request, will search against all search providers. * @param request the request object that contains parameters to base the search on. * * @experimental */ search(request: SearchRequest): Promise<SearchProviderResponseGeneratorExtended>; /** * Register a search provider. * @param provider the search provider to register. */ register(provider: SearchProvider): Promise<RegistrationMetaInfo>; /** * Deregister a search provider by its name. * @param name the name of the search provider to deregister */ deregister(name: string): Promise<void>; /** * Dispatch a search result back to the search provider. * It is then the search providers duty to perform what ever action was chosen. * @param providerId the id of the search provider to send the search result back to. * @param result the search result to send back to the search provider. * @param action the action for the search provider to perform with the search result. * @param identity optionally provide the identity of the dispatcher, otherwise the current identity will be used. */ dispatch(providerId: string, result: SearchResult, action: Action, identity?: OpenFin.Identity): Promise<any>; /** * Disconnect from the search topic. * NOTE: All search providers registered by this search client will be deregistered. */ disconnect(): Promise<void>; /** The channel client for the search topic. */ channel: OpenFin.ChannelClient; } /** * A search topic created by the primary node. */ export interface SearchTopic extends Omit<SearchTopicClient, 'channel'> { /** * Add a subscription listener that will be called when ever a search client subscribes * to this topic. * * Returning false in said listener will reject the request. * @param listener the listener to add. */ onSubscription(listener: SubscriptionListener): void; /** * Remove a listener. * @param listener the listener to remove. */ removeListener(listener: (...args: any[]) => any): void; /** * Add a listener that will be called when ever a search client disconnects from this topic. * @param listener the listener to add. */ onDisconnect(listener: DisconnectListener): void; /** * Add a listener that will be called whenever a search provider registers * @param listener the listener to add */ onRegister(listener: RegisterListener): void; /** * Add a listener that will be called whenever a search provider deregisters * @param listener the listener to add. */ onDeregister(listener: DeregisterListener): void; /** The channel provider for the search topic. */ channel: OpenFin.ChannelProvider; } /** * Information about a search provider. */ export interface SearchProviderInfo { /** * A unique ID used to identify the search provider. */ id: string; /** * A UI friendly title for the search provider. */ title: string; /** * The OpenFin identity that registered this search provider. */ identity?: OpenFin.Identity; /** * The order to sort the score in. The default is `ascending`. * @experimental */ scoreOrder?: ScoreOrder; /** * A keycode that can be used to interact with this Search Provider. */ commandCode?: string; /** * A short description of the Search Provider. */ description?: string; /** * An icon that a UI can display for the Search Provider. */ icon: string; /** * A flag to indicate this provider will not be displayed as a command. */ hidden?: boolean; /** * A title to display above the result list in a UI when targeting this specific Search Provider. */ listTitle?: string; /** * The placeholder string to be displayed in a UI when targeting this specific Search Provider. */ inputPlaceholder?: string; /** * Logo to show render when targeting this specific Search Provider. */ logoUrl?: string; /** * If set, focusing on a search result will trigger onResultDispatch callback. */ dispatchFocusEvents?: boolean; /** * version of client SDK, set by the API */ clientAPIVersion?: string; } /** * The order to sort scored search results in. */ export type ScoreOrder = 'ascending' | 'descending'; /** * The reason which triggered the search result dispatch callback. */ export declare enum ActionTrigger { /** * The search result dispatch was triggered with a regular user action (click, hotkey, etc.) */ UserAction = "user-action", /** * The search result was dispatched back because the user has focused on another search result. */ FocusChange = "focus-change", /** * The search result was dispatched back because there was a load error and the user requested a reload. */ Reload = "reload" } /** * Each action is defined by its title and a hotkey */ export type Action = { name: string; hotkey?: string; }; export declare enum SearchTagBackground { Active = "active", Default = "default" } export interface SearchTag { name: string; background: SearchTagBackground; } /** * Common properties of a {@link SearchResult | search result}. */ export interface SearchResult<A extends Action = Action> { /** * A unique ID for the search result. * Can be used to update a previously returned search result by calling * `searchRequestContext.respond(result)` with the same search result key. */ key: string; /** * UI friendly name for the search result. */ title: string; /** * Unused. * @experimental */ description?: string; /** * Unused. * @experimental */ shortDescription?: string; /** * An optional icon that can be used when displaying the search result in a UI. */ icon?: string; /** * Used when sorting a list of search results for a single provider. * @experimental */ score?: number; /** * Additional custom metadata about the search result. * Can be used when actioning the search result. */ data?: any; /** * Actions that can be performed with this search result. * Used when dispatching search results back to the respective provider. */ actions: A[]; /** * Tags associated with the search result. */ tags?: SearchTag[]; /** * A label to render with the search result. */ label?: string; } /** * Representation of a search request passed as a parameter to a {@link SearchProvider | SearchProvider's} `onUserInput` listener function. * * ```js * const provider = { * name: "my-provider", * title: "My Provider", * onUserInput: (request) => { * const query = request.query; * return getMyResults(query); * } * }; * ``` */ export interface SearchListenerRequest extends SearchRequest { /** * The ID of the search request. * Can be used to tie related search requests together between providers. */ id: string; /** * Registers a listener that is called when the search request is * closed by the search requester. * * Can be used to cleanup pending queries: * ```js * async function onUserInput(request) { * const myQuery = makeQuery(request.query); * * request.onClose(() => { * myQuery.cancel(); * }); * * const results = await myQuery.getResults(); * return { results }; * } * ``` * * @param listener the listener to call when the request is closed. */ onClose(listener: () => void): void; /** * Remove a registered listener. * * ```ts * * function myListener(request, listener) { * // Do something * } * * request.removeListener(myListener); * ``` * @param listener the listener to remove. */ removeListener(listener: () => void): void; } /** * Representation of a search response from a specific invocation of a {@link SearchProvider | SearchProvider's} `onUserInput` listener function. * Can optionally be used to push search results to the requester. * * ```js * function onUserInput(searchListenerRequest, searchListenerResponse) { * searchListenerResponse.open(); * * const myLongRunningQuery = makeMyLongRunningQuery(searchListenerRequest.query); * myLongRunningQuery.onNewResults(myNewResults => { * searchListenerResponse.respond(myNewResults); * }); * * searchListenerRequest.onClose(() => { * myLongRunningQuery.close(); * }); * } * ``` */ export interface SearchListenerResponse { /** * Open the response stream, notifying the search requester that * there are new or updated search results that have yet to be pushed * by the current provider. * @experimental * * ```ts * import type { SearchListenerResponse } from './my-shape-definition'; * function openStream(response:SearchListenerResponse) { * response.open(); * } * * openStream(); * ``` */ open(): void; /** * Close the response stream. * This notifies the requester that the current search provider is done sending results. * * ```ts * import type { SearchListenerResponse } from './my-shape-definition'; * function closeStream(request:SearchListenerRequest, response:SearchListenerResponse) { * response.close(); * } * * closeStream(); * ``` * @experimental */ close(): void; /** * Respond to the search request with new or updated search results. * * ```ts * * response.respond([ * { name: 'result-1' }, * { name: 'result-2' }, * { name: 'result-3' }, * ]); * * ``` * * @param results new or updated search results to respond with. * @experimental */ respond(results: SearchResult[]): void; /** * Remove a search result from the list of responded search results. * * ```ts * response.revoke({ name: 'result-1' }, { name: 'result-2' }); * ``` * @param resultKeys the keys of the search results to revoke. * @experimental */ revoke(...resultKeys: string[]): void; /** * Respond to the search request with new or updated search results context. * @param context The new or updated search result context to respond with. */ updateContext(context: any): void; } /** * An object resolved from 'onUserInput' function containing results and optional context */ export interface SearchResponse { results: SearchResult[]; context?: any; } /** * A function that listens for search requests on a search topic. * Returns a set of search results based on arguments provided. * @param request - The search request coming in * @param response - EXPERIMENTAL - streaming response */ export type UserInputListener = (request: SearchListenerRequest, response: SearchListenerResponse) => Promise<SearchResponse>; /** * The triggered action that should be performed by the search provider. */ export type DispatchedAction = Action & { trigger: ActionTrigger; }; /** * A search result that has been dispatched back to the {@link SearchProvider | SearchProvider's} `onResultDispatch` listener function. * Contains the action that should be performed by the search provider. * * ```js * const provider = { * name: "my-provider", * title: "My Provider", * onUserInput: myOnUserInput, * onResultDispatch: (dispatchedSearchResult) => { * if (dispatchedSearchResult.action.name === "my-action") { * doMyAction(dispatchedSearchResult); * } * } * }; * ``` */ export interface DispatchedSearchResult extends SearchResult { /** * The selected action for the search provider to perform. */ action: DispatchedAction; /** * The OpenFin identity that dispatched this search result. */ dispatcherIdentity: OpenFin.Identity; } /** * A listener called when a search result generated by this provider is dispatched. * * ```js * searchTopic.dispatch("My Provider Name", searchResult, "My Action"); * ``` */ export type ResultDispatchListener = (result: DispatchedSearchResult) => void; /** * A search provider listens for search requests on a search topic and returns search results. * It optionally can also perform custom actions when a search result is dispatched back to the provider. */ export interface SearchProvider extends SearchProviderInfo { /** * The search listener for the search provider. * * When a search is requested on the subscribed search topic, this * listener will be called and have the opportunity to return search results. */ onUserInput: UserInputListener; /** * An optional listener for actioning search results. * * When this search provider returns search results via its `onUserInput` listener, * the receiver of the results can select and dispatch a single result back to the provider. * * It is then up to the search provider to perform the custom requested action. */ onResultDispatch?: ResultDispatchListener; }