Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@openfin/search-api

Package Overview
Dependencies
Maintainers
36
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@openfin/search-api

A search API framework for OpenFin.

  • 1.5.9
  • latest
  • npm
  • Socket score

Version published
Weekly downloads
126
increased by530%
Maintainers
36
Weekly downloads
 
Created
Source

The Search Extension is a framework for searching, fetching, aggregating and actioning data through application interopability.

Getting Started

There are two options for using this package.

Import functions from NPM package and bundle:

import { create, subscribe } from '@openfin/search-api';

Or import the script fron our CDN and use the fin.Search global namespace.

<script src="https://cdn.openfin.co/search-api/index.js" />
<script>
    const create = fin.Search.create;
    const subscribe = fin.Search.subscribe;
</script>

API Reference

More in depth API documentation can be found here.

Examples

Searching for Data

// It is recommended to bundle and import search API functions.
// However, the global `fin.Search` namespace can be used as an alternative.
import { subscribe } from '@openfin/search-api';

// Subscribe to a search topic.
const searchTopic = await subscribe({ topic: 'foo' });

/* Search for data with query `bar`.
   This will return a generator which can be called multiple times
   while there are pending responses from search data providers. */
const generator = searchTopic.search({ query: 'bar' });
while (true) {
    const { value, done } = await generator.next();

    // Implementation specific rendering logic.
    render(results);

    // If done is true, all search providers have responded with their data.
    if (done) {
        break;
    }
}

// When done with search request, call close.
generator.close();

Registering a Search Provider

// It is recommended to bundle and import search API functions.
// However, the global `fin.Search` namespace can be used as an alternative.
import { subscribe } from '@openfin/search-api';

const openWindowAction = 'Open Window';

// Example search handler that returns results from a backend query.
async function getSearchResults({ query }) {
    const res = await fetch('/search?q=' + encodeURIComponent(query));
    if (!res.ok) {
        throw new Error('uh oh something went wrong');
    }
    const json = await res.json();

    /* Return initial search results.

       All results must have the `name` and `description`
       field at the very least for rendering purposes. */
    return json.map((myResult) => ({
        name: myResult.nameAttribute,
        shortDescription: myResult.shortDescriptionAttribute,
        description: myResult.descriptionAttribute,
        actions: [openWindowAction], // Dispatchable actions for this search result.
        data: myResult.customMetadata
    }));
}

// Example function for actioning a result from `getSearchResults`.
function openWindowForSearchResult(result) {
    const dispatchedAction = result.action; // `result.action` is set to the action that was dispatched.
    if (dispatchedAction !== openWindowAction) return;
    window.open(result.data.url);
}

// Subscribe to a search topic.
const searchTopic = await subscribe({ topic: 'foo' });

/* The `name` and `onSearch` attributes are required for a data provider.

   The `onSearch` function will be called back when the topic is searched
   on. (ex. `searchTopic.search("my query")`)

   The `onResultDispatch` function will be called back when a search result
   is dispatched. (ex. `searchTopic.dispatch("Provider Name", searchResult, "Open Window")`) */
const provider = {
    name: 'bar',
    onSearch: getSearchResults,
    onResultDispatch: openWindowForSearchResult
};

// Register the search data provider.
await searchTopic.register(provider);

Actioning Search Results

// It is recommended to bundle and import search API functions.
// However, the global `fin.Search` namespace can be used as an alternative.
import { subscribe } from '@openfin/search-api';

// Subscribe to a search topic.
const searchTopic = await subscribe({ topic: 'foo' });

// Get search results.
const generator = searchTopic.search({ query: 'bar' });
const { value } = await generator.next();

/* Dispatches the first search result in the first response back to the
   respective provider, such that the provider can action the result. */
const firstSearchProviderResponse = value[0];
const firstSearchProviderName = firstSearchProviderResponse.provider.name;
const firstSearchResult = firstSearchProviderResponse.results[0];
const firstSearchAction = firstSearchResult.actions[0];
await searchTopic.dispatch(firstSearchProviderName, firstSearchResult, firstSearchAction); // Omitting will default to first action in `result.actions`.

Control Search Topic Subscriptions

// It is recommended to bundle and import search API functions.
// However, the global `fin.Search` namespace can be used as an alternative.
import { create } from "@openfin/search-api";

const searchTopic = await create({ topic: "foo" });

// Only hosts in the list can subscribe to the search topic.
const allowedHosts = ["www.vendor.com"];
searchTopic.onSubscription(identity => {
    // Get the URL of the subscribing identity.
    const info = await fin.View.wrapSync(identity).getInfo();
    const url = new URL(info.url);

    return allowedHosts.includes(url.host);
});

List Search Providers

// It is recommended to bundle and import search API functions.
// However, the global `fin.Search` namespace can be used as an alternative.
import { create } from '@openfin/search-api';

// Subscribe or create a search topic.
const searchTopic = await create({ topic: 'foo' });

// Returns a list of provider info objects.
const info = await searchTopic.getAllProviderInfo();

for (let provider of info) {
    console.log(`Provider Name: ${provider.name}, Openfin Identity: ${provider.identity}`);
}

Searching Specific Providers

// It is recommended to bundle and import search API functions.
// However, the global `fin.Search` namespace can be used as an alternative.
import { create } from '@openfin/search-api';

// Subscribe or create a search topic.
const searchTopic = await create({ topic: 'foo' });

// Only searches against providers in the provider name list.
searchTopic.searchProviders(['Provider Name 1', 'Provider Name 2'], 'bar');

Pushing Search Results

For simple use cases, the Search Extension allows search providers to register an async handler function that returns a set of search results. Internally the Search Extension uses a pull architecture, allowing the search requester to pull in an initial set of results from all search providers listening in on a search topic.

// A simple search handler that returns an initial set of search results.
async function getSearchResults({ query }) {
    const res = await fetch('/search?q=' + encodeURIComponent(query));
    if (!res.ok) {
        throw new Error('uh oh something went wrong');
    }
    const json = await res.json();

    // These results will be pulled in by the search requester.
    return json.map((myResult) => ({
        name: myResult.nameAttribute,
        shortDescription: myResult.shortDescriptionAttribute,
        description: myResult.descriptionAttribute,
        actions: [openWindowAction],
        data: myResult.customMetadata
    }));
}

For a more complex use case, like a long running query, it might be desired to push new or updated search results to the search requester after a long period of time. For said use case, you can use the search listener response object as highlighted in the example below.

/* An advanced search handler that pushes new or updated search results
   as long as the search request has not been closed. */
async function getSearchResults(request, response) {
    /* ID of the search request.
       Can be used to tie related search providers together. */
    const id = request.id;

    // The search query.
    const query = request.query;

    /* ▼ PUSH ARCHITECTURE ▼ */

    /* 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. */
    response.open();

    const myLongRunningQuery = makeMyLongRunningQuery(query);

    // On new or updated search results push them to the search requester.
    const onNewResults = (myResults) => {
        // Map the new results.
        const newResults = myResults.map((myResult) => ({
            key: myResult.keyAttribute,
            name: myResult.nameAttribute,
            shortDescription: myResult.shortDescriptionAttribute,
            description: myResult.descriptionAttribute,
            actions: [openWindowAction],
            data: myResult.customMetadata
        }));

        /* Push the new results to the search requester.

         If the `key` attribute matches a previously pushed search result,
         the old result will be updated with the new result's content. */
        response.respond(newResults);
    };
    myLongRunningQuery.onNewResults(onNewResults);

    /* Remove the listener and close the long running query if
       the request has been closed by the search requester. */
    request.onClose(() => {
        myLongRunningQuery.close();
    });

    /**
     * Upon query completion, close the response. This notifies
     * the requester that the current search provider is done sending results.
     */
    myLongRunningQuery.onQueryDone(() => {
        response.close();
    });
}

Keywords

FAQs

Package last updated on 20 Aug 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc