Skip to content

Commit

Permalink
Extracted search and web-worker utilities into separate js-worker-sea…
Browse files Browse the repository at this point in the history
…rch library.
  • Loading branch information
bvaughn committed Dec 30, 2015
1 parent fff470e commit 0f8f911
Show file tree
Hide file tree
Showing 15 changed files with 30 additions and 656 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

# 2.0.0
Extract web-worker search utilty into its own NPM package, [js-worker-search](https://github.com/bvaughn/js-worker-search). Moved web-worker support detection (previously managed by `CapabilitiesBasedSearchApi`) into that module as well to simplify the redux-search interface.

### Upgrade path (1.x to 2.x)
If you were previously importing `CapabilitiesBasedSearchApi` or `WorkerSearchApi` directly you should now just import `SearchApi`. It will handle auto-detecting web-worker support and use the correct implementation under the hood.

`SearchUtility` will now longer be exported by this package. Import it from [js-worker-search](https://github.com/bvaughn/js-worker-search) instead.

# 1.0.0
Result selector created by `getSearchSelectors` automatically filters the result list to ensure that all results are all present in the resource collection. (See issue #29 for more background information.)

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ redux-search

[![Circle CI][circle-image]][circle-url]

Higher-order Redux library for searching collections of objects. Search algorithms based on [js-search](https://github.com/bvaughn/js-search) but with added web-worker support for better performance.
Higher-order Redux library for searching collections of objects. Search algorithms powered by [js-worker-search](https://github.com/bvaughn/js-worker-search).

Check out the live demo at [treasure-data.github.io/redux-search](http://treasure-data.github.io/redux-search/)

Expand Down Expand Up @@ -35,7 +35,7 @@ redux-search watches the store for changes to searchable collections and automat

```javascript
import { applyMiddleware, combineReducers, compose, createStore } from 'redux'
import { reducer as searchReducer, reduxSearch } from '../src/index'
import { reducer as searchReducer, reduxSearch } from 'redux-search'

// Configure reducer to store state at state.search
// You can store it elsewhere but you will need to supply your own :searchStateSelector
Expand Down
38 changes: 6 additions & 32 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ redux-search provides the following named exports:
* [`getSearchSelectors`](#getsearchselectors-filterfunction-resourcename-resourceselector-searchstateselector-)
* [`reducer`](#reducer)
* [`reduxSearch`](#reduxsearch-resourceindexes-resourceselector-searchapi-searchstateselector-)
* [`CapabilitiesBasedSearchApi`](#searchapi--workersearchapicapabilitiesbasedsearchapi)
* [`SearchApi`](#searchapi--workersearchapi)
* [`SearchUtility`](#searchutility)
* [`WorkerSearchApi`](#searchapi--workersearchapi)
* [`SearchApi`](#searchapi--searchapi)

### `createSearchAction(resourceName)`
Factory function that creates Redux search actions. This function requires a single parameter (a `resourceName` string) that identifies a searchable resource. For example:
Expand Down Expand Up @@ -102,42 +99,19 @@ Observable Search API. Should only be overridden for testing purposes. Refer to
##### searchStateSelector:
Selects the search sub-state within the state store. A default implementation is provided. Override only if you add `searchReducer()` to the store somewhere other than `state.search`.

### `SearchUtility`
### `SearchApi`
+The search API is an observable that manages communication between the redux-search middleware and the underlying search utility. It maps resource names to search indicies and coordinates searches. It supports both single-threaded and web-worker modes and will determine which to use automatically based on the capabilities of the current environment.

Forked from [JS search](github.com/bvaughn/js-search), this utility builds a search index and runs actual searches. One instance of `SearchUtility` is created for each searchable resource type in redux-search. Depending on how [`reduxSearch`](#reduxsearch-resourceindexes-resourceselector-searchapi-searchstateselector-) has been configured this instance may live in the UI thread or in a web-worker.

In most cases this utility does not need to be used directly. redux-search will automatically create and configure searchable instances in response to store changes. The utility is exposed though in case custom search functionality is needed that falls outside of the primary scope of redux-search. In that case you can build and run your own searches using the following methods:

##### `indexDocument (uid, text)`
Adds or updates a uid in the search index and associates it with the specified text. Note that at this time uids can only be added or updated in the index, not removed.

* **uid**: Uniquely identifies a searchable object
* **text**: Searchable text to associate with the uid

##### `search(query)`
Searches the current index for the specified query text. Only uids matching all of the words within the text will be accepted. If an empty query string is provided all indexed uids will be returned.

Document searches are case-insensitive (e.g. "search" will match "Search"). Document searches use substring matching (e.g. "na" and "me" will both match "name").

* **query**: Searchable query text

This method will return an array of uids.

### `SearchApi` / `WorkerSearchApi` / `CapabilitiesBasedSearchApi`
+The search API is an observable that manages communication between the redux-search middleware and the underlying search utility. It maps resource names to search indicies and coordinates searches. Both a single-threaded implementation (`SearchApi`) and a web-worker implementation (`WorkerSearchApi`) are provided.

By default a capabilities-based search API is used (`CapabilitiesBasedSearchApi`) that auto-detects web worker support and uses the best implementation for the current environment. You can override this behavior with `reduxSearch()` for testing purposes like so:
You can override this API with `reduxSearch()` (for testing purposes) like so:

```javascript
import { SearchApi } from './SearchApi'

reduxSearch({
// Configure :resourceIndexes and :resourceSelector here and then...
searchApi = new SearchApi()
searchApi = new StubSearchApi()
})
```

You may also want to override this value for unit testing purposes. To do so you will need to implement the following methods:
In the above example `StubSearchApi` will need to implement the following methods:

##### `subscribe (onNext, onError)`
Subscribe to Search events. Subscribers will be notified each time a Search is performed.
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@
"gh-pages": "^0.8.0",
"html-webpack-plugin": "^1.7.0",
"immutable": "^3.7.5",
"js-worker-search": "file:///Users/brianvaughn/Documents/git/js-worker-search/js-worker-search-1.0.0.tgz",
"keymirror": "^0.1.1",
"react": "^0.14.3",
"react-dom": "^0.14.3",
"react-highlight-words": "^0.1.1",
"react-redux": "^4.0.0",
"react-virtualized": "^2.1.0",
"redux-thunk": "^1.0.0",
Expand All @@ -73,12 +75,10 @@
"tape": "^4.2.2",
"watch": "^0.16.0",
"webpack": "^1.12.9",
"webpack-dev-server": "^1.14.0",
"worker-loader": "^0.7.0"
"webpack-dev-server": "^1.14.0"
},
"dependencies": {
"node-uuid": "^1.4.7",
"react-highlight-words": "^0.1.1",
"js-worker-search": "file:///Users/brianvaughn/Documents/git/js-worker-search/js-worker-search-1.0.0.tgz",
"redux": "^3.0.4"
}
}
52 changes: 5 additions & 47 deletions src/SearchApi.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
/** @flow */
import WorkerSearch, { Search } from './lib'
import Search from 'js-worker-search'

/**
* Observable that manages communication between redux-search middleware and the Search utility.
* This class maps resource names to search indicies and manages subscribers.
*/
export class SubscribableSearchApi {
export default class SubscribableSearchApi {

/**
* Constructor.
*
* @param createSearch Factory function responsible for creating a Search instance
*/
constructor (createSearch) {
this._createSearch = createSearch
constructor () {
this._resourceToSearchMap = {}

// Subscribers
Expand Down Expand Up @@ -59,7 +56,7 @@ export class SubscribableSearchApi {
* @param resources Map of resource uid to resource (Object)
*/
indexResource (resourceName, fieldNamesOrIndexFunction, resources) {
const search = this._createSearch()
const search = new Search()

if (Array.isArray(fieldNamesOrIndexFunction)) {
if (resources.forEach instanceof Function) {
Expand Down Expand Up @@ -98,9 +95,7 @@ export class SubscribableSearchApi {
async performSearch (resourceName, text) {
try {
const search = this._resourceToSearchMap[resourceName]

// Promise.resolve handles both synchronous and web-worker versions of Search
const result = await Promise.resolve(search.search(text))
const result = await search.search(text)

this._notifyNext({
result,
Expand Down Expand Up @@ -130,40 +125,3 @@ export class SubscribableSearchApi {
)
}
}

/**
* Single-threaded search API.
* This implementation is provided for browsers that do not support web workers.
*/
export class SearchApi extends SubscribableSearchApi {
constructor () {
super(() => new Search())
}
}

/**
* Web worker search API.
* Indexing and searching is performed in a web worker thread.
*/
export class WorkerSearchApi extends SubscribableSearchApi {
constructor () {
super(() => new WorkerSearch())
}
}

/**
* Search API that uses web workers when available.
* Indexing and searching is performed in the UI thread as a fallback when web workers aren't supported.
*/
export class CapabilitiesBasedSearchApi extends SubscribableSearchApi {
constructor () {
// Based on https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
// But with added check for Node environment
if (typeof window !== 'undefined' && window.Worker) {
super(() => new WorkerSearch())
} else {
super(() => new Search())
}
}
}

2 changes: 1 addition & 1 deletion src/SearchApi.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'tape'
import { SearchApi } from './SearchApi'
import SearchApi from './SearchApi'

function getSearchApi () {
const documentA = {id: 1, name: 'One', description: 'The first document'}
Expand Down
12 changes: 2 additions & 10 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@ import {
import { search } from './actions'
import reduxSearch from './reduxSearch'
import reducer from './reducer'
import {
CapabilitiesBasedSearchApi,
SearchApi,
WorkerSearchApi
} from './SearchApi'
import { Search } from './lib'
import SearchApi from './SearchApi'

export default reduxSearch
export {
Expand All @@ -20,8 +15,5 @@ export {
reducer,
reduxSearch,
search as createSearchAction,
Search as SearchUtility,
CapabilitiesBasedSearchApi,
SearchApi,
WorkerSearchApi
SearchApi
}
97 changes: 0 additions & 97 deletions src/lib/Search.js

This file was deleted.

Loading

0 comments on commit 0f8f911

Please sign in to comment.