diff --git a/README.md b/README.md index b68b166349..34aa2a81d3 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ InstantSearch.js is a vanilla JavaScript library that lets you create an instant - [Why](#why) - [Getting started](#getting-started) +- [Installation](#installation) - [Documentation](#documentation) - [Demos](#demos) - [Playground](#playground) @@ -52,9 +53,8 @@ Using InstantSearch.js is as simple as adding this JavaScript code to your page: ```javascript // 1. Instantiate the search const search = instantsearch({ - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', indexName: 'instant_search', + searchClient: algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'), }); // 2. Create an interactive search box @@ -97,6 +97,14 @@ search.start(); To learn more about the library, follow the [getting started](https://community.algolia.com/instantsearch.js/v2/getting-started.html) guide or check how to [add it to your own project](https://community.algolia.com/instantsearch.js/v2/guides/usage.html). +## Installation + +```sh +npm install instantsearch.js algoliasearch +# or +yarn add instantsearch.js algoliasearch +``` + ## Documentation The documentation is available at [community.algolia.com/instantsearch.js](https://community.algolia.com/instantsearch.js). diff --git a/dev/app/builtin/stories/hits.stories.js b/dev/app/builtin/stories/hits.stories.js index c014002010..7cfa069403 100644 --- a/dev/app/builtin/stories/hits.stories.js +++ b/dev/app/builtin/stories/hits.stories.js @@ -1,6 +1,7 @@ /* eslint-disable import/default */ import { storiesOf } from 'dev-novel'; +import algoliasearch from 'algoliasearch/lite'; import instantsearch from '../../../../index'; import { wrapWithHits } from '../../utils/wrap-with-hits.js'; @@ -64,9 +65,11 @@ export default () => { ); }, { - appId: 'KY4PR9ORUL', - apiKey: 'a5ca312adab3b79e14054154efa00b37', indexName: 'highlight_array', + searchClient: algoliasearch( + 'KY4PR9ORUL', + 'a5ca312adab3b79e14054154efa00b37' + ), } ) ); diff --git a/dev/app/utils/wrap-with-hits.js b/dev/app/utils/wrap-with-hits.js index afa8acb09a..682c1a1b98 100644 --- a/dev/app/utils/wrap-with-hits.js +++ b/dev/app/utils/wrap-with-hits.js @@ -1,6 +1,7 @@ /* eslint-disable import/default */ import { action } from 'dev-novel'; +import algoliasearch from 'algoliasearch/lite'; import instantsearch from '../../../index.js'; import item from './item.html'; import empty from './no-results.html'; @@ -10,18 +11,16 @@ export const wrapWithHits = ( instantSearchConfig = {} ) => container => { const { - appId = 'latency', - apiKey = '6be0576ff61c053d5f9a3225e2a90f76', indexName = 'instant_search', + searchClient = algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'), searchParameters = {}, ...otherInstantSearchConfig } = instantSearchConfig; const urlLogger = action('Routing state'); window.search = instantsearch({ - appId, - apiKey, indexName, + searchClient, searchParameters: { hitsPerPage: 3, ...searchParameters, diff --git a/docgen/assets/js/bindRunExamples.js b/docgen/assets/js/bindRunExamples.js index 95307362c0..abbe9bdf3f 100644 --- a/docgen/assets/js/bindRunExamples.js +++ b/docgen/assets/js/bindRunExamples.js @@ -1,16 +1,17 @@ import instantsearch from "../../../src/lib/main.js"; +import algoliasearch from "algoliasearch/lite"; import capitalize from "lodash/capitalize"; window.instantsearch = instantsearch; window.search = instantsearch({ - appId: "latency", - apiKey: "6be0576ff61c053d5f9a3225e2a90f76", - indexName: "instant_search", - urlSync: false, + indexName: window.searchConfig.indexName || "instant_search", + searchClient: algoliasearch( + window.searchConfig.appId || "latency", + window.searchConfig.apiKey || "6be0576ff61c053d5f9a3225e2a90f76" + ), searchParameters: { - hitsPerPage: 3 - }, - ...window.searchConfig + hitsPerPage: 3, + } }); const el = html => { diff --git a/docgen/src/examples/calendar-widget/app.js b/docgen/src/examples/calendar-widget/app.js index d61f8beca8..f8b3892a3b 100644 --- a/docgen/src/examples/calendar-widget/app.js +++ b/docgen/src/examples/calendar-widget/app.js @@ -1,10 +1,9 @@ const ONE_DAY_IN_MS = 3600 * 24 * 1000; const search = instantsearch({ - appId: 'latency', - apiKey: '059c79ddd276568e990286944276464a', indexName: 'concert_events_instantsearchjs', - routing: true + searchClient: algoliasearch('latency', '059c79ddd276568e990286944276464a'), + routing: true, }); search.addWidget( diff --git a/docgen/src/examples/calendar-widget/index.html b/docgen/src/examples/calendar-widget/index.html index bd8b243549..f01ff50615 100644 --- a/docgen/src/examples/calendar-widget/index.html +++ b/docgen/src/examples/calendar-widget/index.html @@ -42,7 +42,8 @@

Dates

- + + diff --git a/docgen/src/examples/e-commerce/index.html b/docgen/src/examples/e-commerce/index.html index 4840d9cbd2..f004fc00d1 100644 --- a/docgen/src/examples/e-commerce/index.html +++ b/docgen/src/examples/e-commerce/index.html @@ -55,4 +55,5 @@ + diff --git a/docgen/src/examples/e-commerce/search.js b/docgen/src/examples/e-commerce/search.js index 66717061ab..7f88d8702f 100644 --- a/docgen/src/examples/e-commerce/search.js +++ b/docgen/src/examples/e-commerce/search.js @@ -1,10 +1,9 @@ 'use strict'; -/* global instantsearch */ +/* global instantsearch algoliasearch */ var search = instantsearch({ - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', indexName: 'instant_search', + searchClient: algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'), routing: true }); @@ -143,21 +142,6 @@ search.addWidget( }) ); -search.addWidget( - instantsearch.widgets.priceRanges({ - container: '#prices', - attributeName: 'price', - cssClasses: { - list: 'nav nav-list', - count: 'badge pull-right', - active: 'active' - }, - templates: { - header: '
Prices
' - } - }) -); - search.addWidget( instantsearch.widgets.sortBy({ container: '#sort-by', @@ -170,17 +154,17 @@ search.addWidget( }) ); -search.addWidget( - instantsearch.widgets.clearAll({ - container: '#clear-all', - templates: { - link: ' Clear all filters' - }, - cssClasses: { - root: 'btn btn-block btn-default' - }, - autoHideContainer: true - }) -); +// search.addWidget( +// instantsearch.widgets.clearAll({ +// container: '#clear-all', +// templates: { +// link: ' Clear all filters' +// }, +// cssClasses: { +// root: 'btn btn-block btn-default' +// }, +// autoHideContainer: true +// }) +// ); search.start(); diff --git a/docgen/src/examples/getting-started-boilerplate/index.html b/docgen/src/examples/getting-started-boilerplate/index.html index c44c710026..549adff62e 100644 --- a/docgen/src/examples/getting-started-boilerplate/index.html +++ b/docgen/src/examples/getting-started-boilerplate/index.html @@ -41,7 +41,8 @@ - + + diff --git a/docgen/src/examples/media/index.html b/docgen/src/examples/media/index.html index 6e1c897047..4bb562ab5c 100644 --- a/docgen/src/examples/media/index.html +++ b/docgen/src/examples/media/index.html @@ -31,4 +31,5 @@
Ratings
+ diff --git a/docgen/src/examples/media/search.js b/docgen/src/examples/media/search.js index 05136cb24b..11bdc219c1 100644 --- a/docgen/src/examples/media/search.js +++ b/docgen/src/examples/media/search.js @@ -1,9 +1,8 @@ -/* global instantsearch */ +/* global instantsearch algoliasearch */ var search = instantsearch({ - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', indexName: 'movies', + searchClient: algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'), routing: true }); diff --git a/docgen/src/examples/tourism/index.html b/docgen/src/examples/tourism/index.html index 05126caf17..a95066cbb6 100644 --- a/docgen/src/examples/tourism/index.html +++ b/docgen/src/examples/tourism/index.html @@ -72,5 +72,5 @@ - + diff --git a/docgen/src/examples/tourism/search.js b/docgen/src/examples/tourism/search.js index d7a25dad0c..ff8cf9d7bf 100644 --- a/docgen/src/examples/tourism/search.js +++ b/docgen/src/examples/tourism/search.js @@ -1,9 +1,8 @@ -/* global instantsearch */ +/* global instantsearch algoliasearch */ window.addEventListener('load', function() { var search = instantsearch({ - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', + searchClient: algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'), indexName: 'airbnb', routing: true }); diff --git a/docgen/src/getting-started.md.hbs b/docgen/src/getting-started.md.hbs index 1ad28354c1..68ce6b04b6 100644 --- a/docgen/src/getting-started.md.hbs +++ b/docgen/src/getting-started.md.hbs @@ -60,9 +60,10 @@ The jsDeliver CDN is highly available with [over 110 locations](https://www.jsde If you have a JavaScript build system, you can install **InstantSearch.js** from NPM: ```javascript -// `npm install instantsearch.js --save` OR -// `yarn add instantsearch.js` +// `npm install instantsearch.js algoliasearch` OR +// `yarn add instantsearch.js algoliasearch` +const algoliasearch = require('algoliasearch/lite'); const instantsearch = require('instantsearch.js'); ``` @@ -86,9 +87,8 @@ To initialize with the credentials proposed at the beginning: ```javascript const search = instantsearch({ - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', indexName: 'instant_search', + searchClient: algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'), routing: true }); diff --git a/docgen/src/guides/angular-integration.md b/docgen/src/guides/angular-integration.md index 41447e6575..10a8f7dbe0 100644 --- a/docgen/src/guides/angular-integration.md +++ b/docgen/src/guides/angular-integration.md @@ -70,9 +70,8 @@ import instantsearch from 'instantsearch.js/es'; @Injectable() export class InstantSearchService { search = instantsearch({ - appId: 'latency', - apiKey: '3d9875e51fbd20c7754e65422f7ce5e1', indexName: 'bestbuy', + searchClient: algoliasearch('latency', '3d9875e51fbd20c7754e65422f7ce5e1'), urlSync: true }); diff --git a/docgen/src/guides/custom-widget.md b/docgen/src/guides/custom-widget.md index ddd0f4c7f9..8f8aee5982 100644 --- a/docgen/src/guides/custom-widget.md +++ b/docgen/src/guides/custom-widget.md @@ -117,9 +117,8 @@ the DOM is already set up. You can [see the example live](https://jsfiddle.net/b ```javascript const search = instantsearch({ - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', indexName: 'movies', + searchClient: algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'), }); search.addWidget({ diff --git a/docgen/src/guides/opensearch.md b/docgen/src/guides/opensearch.md index 91692cc8db..52c211abb1 100644 --- a/docgen/src/guides/opensearch.md +++ b/docgen/src/guides/opensearch.md @@ -35,9 +35,8 @@ started, you need to add this to the initialization of InstantSearch.js: ```diff const search = instantsearch({ - appId: opts.appId, - apiKey: opts.apiKey, indexName: opts.indexName, + searchClient: algoliasearch(opts.appId, opts.apiKey), + urlSync: true, }); ``` diff --git a/functional-tests/app/app.js b/functional-tests/app/app.js index f2660b10fa..eb12072744 100644 --- a/functional-tests/app/app.js +++ b/functional-tests/app/app.js @@ -1,10 +1,9 @@ -/* global instantsearch */ +/* global instantsearch algoliasearch */ /* eslint-disable object-shorthand, prefer-template, prefer-arrow-callback */ var search = instantsearch({ // eslint-disable-line - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', indexName: 'instant_search', + searchClient: algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'), routing: true, searchParameters: { hitsPerPage: 6, diff --git a/package.json b/package.json index 6039f50f36..0ff05e9c3f 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "es" ], "devDependencies": { + "algoliasearch": "3.30.0", "argos-cli": "0.0.9", "autodll-webpack-plugin": "0.3.9", "autoprefixer": "8.1.0", @@ -129,7 +130,6 @@ "webpack-dev-server": "2.11.2" }, "dependencies": { - "algoliasearch": "3.27.0", "algoliasearch-helper": "2.26.0", "classnames": "2.2.5", "events": "1.1.0", diff --git a/src/lib/InstantSearch.js b/src/lib/InstantSearch.js index 0d70b75d2d..d62c41a09a 100644 --- a/src/lib/InstantSearch.js +++ b/src/lib/InstantSearch.js @@ -1,6 +1,5 @@ // we use the full path to the lite build to solve a meteor.js issue: // https://github.com/algolia/instantsearch.js/issues/1024#issuecomment-221618284 -import algoliasearch from 'algoliasearch/src/browser/builds/algoliasearchLite.js'; import algoliasearchHelper from 'algoliasearch-helper'; import forEach from 'lodash/forEach'; import mergeWith from 'lodash/mergeWith'; @@ -22,41 +21,6 @@ const ROUTING_DEFAULT_OPTIONS = { function defaultCreateURL() { return '#'; } -const defaultCreateAlgoliaClient = (defaultAlgoliasearch, appId, apiKey) => - defaultAlgoliasearch(appId, apiKey); - -const checkOptions = ({ - appId, - apiKey, - indexName, - createAlgoliaClient, - searchClient, -}) => { - if (!searchClient) { - if (appId === null || apiKey === null || indexName === null) { - const usage = ` -Usage: instantsearch({ - appId: 'my_application_id', - apiKey: 'my_search_api_key', - indexName: 'my_index_name' -});`; - throw new Error(usage); - } - } else if ( - searchClient && - (indexName === null || - appId !== null || - apiKey !== null || - createAlgoliaClient !== defaultCreateAlgoliaClient) - ) { - const usage = ` -Usage: instantsearch({ - indexName: 'my_index_name', - searchClient: algoliasearch('appId', 'apiKey') -});`; - throw new Error(usage); - } -}; /** * Widgets are the building blocks of InstantSearch.js. Any @@ -78,41 +42,34 @@ class InstantSearch extends EventEmitter { super(); const { - appId = null, - apiKey = null, indexName = null, numberLocale, searchParameters = {}, urlSync = null, routing = null, searchFunction, - createAlgoliaClient = defaultCreateAlgoliaClient, stalledSearchDelay = 200, searchClient = null, } = options; - checkOptions({ - appId, - apiKey, - indexName, - createAlgoliaClient, - searchClient, - }); + if (indexName === null || searchClient === null) { + throw new Error(`Usage: instantsearch({ + indexName: 'indexName', + searchClient: algoliasearch('appId', 'apiKey') +});`); + } - if (searchClient && typeof searchClient.search !== 'function') { + if (typeof searchClient.search !== 'function') { throw new Error( - 'InstantSearch configuration error: `searchClient` must implement a `search(requests)` method.' + 'The search client must implement a `search(requests)` method.' ); } - const client = - searchClient || createAlgoliaClient(algoliasearch, appId, apiKey); - - if (typeof client.addAlgoliaAgent === 'function') { - client.addAlgoliaAgent(`instantsearch.js ${version}`); + if (typeof searchClient.addAlgoliaAgent === 'function') { + searchClient.addAlgoliaAgent(`instantsearch.js ${version}`); } - this.client = client; + this.client = searchClient; this.helper = null; this.indexName = indexName; this.searchParameters = { ...searchParameters, index: indexName }; @@ -157,14 +114,6 @@ class InstantSearch extends EventEmitter { ...ROUTING_DEFAULT_OPTIONS, ...routing, }; - - if (options.createAlgoliaClient) { - // eslint-disable-next-line no-console - console.warn(` -InstantSearch.js: \`createAlgoliaClient\` option is deprecated and will be removed in the next major version. -Please use \`searchClient\` instead: https://community.algolia.com/instantsearch.js/v2/instantsearch.html#struct-InstantSearchOptions-searchClient. -To help you migrate, please refer to the migration guide: https://community.algolia.com/instantsearch.js/v2/guides/prepare-for-v3.html`); - } } /** diff --git a/src/lib/__tests__/InstantSearch-test-2.js b/src/lib/__tests__/InstantSearch-test-2.js index 62b4f27972..fa2001d3c2 100644 --- a/src/lib/__tests__/InstantSearch-test-2.js +++ b/src/lib/__tests__/InstantSearch-test-2.js @@ -3,8 +3,6 @@ import InstantSearch from '../InstantSearch'; jest.useFakeTimers(); -const appId = 'appId'; -const apiKey = 'apiKey'; const indexName = 'lifecycle'; describe('InstantSearch life cycle', () => { @@ -18,11 +16,9 @@ describe('InstantSearch life cycle', () => { }; const search = new InstantSearch({ - appId, - apiKey, indexName, searchFunction: searchFunctionSpy, - createAlgoliaClient: () => fakeClient, + searchClient: fakeClient, }); expect(searchFunctionSpy).not.toHaveBeenCalled(); @@ -63,10 +59,8 @@ describe('InstantSearch life cycle', () => { }; const search = new InstantSearch({ - appId, - apiKey, indexName, - createAlgoliaClient: () => fakeClient, + searchClient: fakeClient, }); const widget = { @@ -144,11 +138,9 @@ describe('InstantSearch life cycle', () => { }; const search = new InstantSearch({ - appId, - apiKey, indexName, searchFunction: searchFunctionSpy, - createAlgoliaClient: () => fakeClient, + searchClient: fakeClient, }); search.start(); @@ -161,10 +153,13 @@ describe('InstantSearch life cycle', () => { }); it('does not break when providing searchFunction with multiple resquests', () => { + const fakeClient = { + search: jest.fn(() => Promise.resolve({ results: [{}] })), + }; + const search = new InstantSearch({ - appId, - apiKey, indexName, + searchClient: fakeClient, searchFunction: h => { h.addDisjunctiveFacetRefinement('brand', 'Apple'); h.search(); diff --git a/src/lib/__tests__/InstantSearch-test-integration.js b/src/lib/__tests__/InstantSearch-test-integration.js index 9bb846c728..1eaaf51d67 100644 --- a/src/lib/__tests__/InstantSearch-test-integration.js +++ b/src/lib/__tests__/InstantSearch-test-integration.js @@ -1,14 +1,17 @@ // import algoliaSearchHelper from 'algoliasearch-helper'; +import algoliasearch from 'algoliasearch'; import InstantSearch from '../InstantSearch'; describe('InstantSearch lifecycle', () => { it('emits an error if the API returns an error', () => { const search = new InstantSearch({ - // correct credentials so that the client does not retry - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', // the index name does not exist so that we get an error indexName: 'DOESNOTEXIST', + // correct credentials so that the client does not retry + searchClient: algoliasearch( + 'latency', + '6be0576ff61c053d5f9a3225e2a90f76' + ), }); let sendError; diff --git a/src/lib/__tests__/InstantSearch-test.js b/src/lib/__tests__/InstantSearch-test.js index 9c18b58c66..9858edac3c 100644 --- a/src/lib/__tests__/InstantSearch-test.js +++ b/src/lib/__tests__/InstantSearch-test.js @@ -19,7 +19,7 @@ describe('InstantSearch lifecycle', () => { let urlSync; beforeEach(() => { - client = { algolia: 'client' }; + client = { search() {} }; helper = algoliaSearchHelper(client); // when using searchFunction, we lose the reference to @@ -55,9 +55,8 @@ describe('InstantSearch lifecycle', () => { InstantSearch.__Rewire__('algoliasearchHelper', helperStub); search = new InstantSearch({ - appId, - apiKey, indexName, + searchClient: algoliasearch(appId, apiKey), searchParameters, urlSync: {}, }); @@ -81,48 +80,6 @@ describe('InstantSearch lifecycle', () => { ); }); - describe('when providing a custom client module', () => { - let createAlgoliaClient; - let customAppID; - let customApiKey; - - beforeEach(() => { - // InstantSearch is being called once at the top-level context, so reset the `algoliasearch` spy - algoliasearch.resetHistory(); - - // Create a spy to act as a clientInstanceFunction that returns a custom client - createAlgoliaClient = sinon.stub().returns(client); - customAppID = 'customAppID'; - customApiKey = 'customAPIKey'; - - // Create a new InstantSearch instance with custom client function - search = new InstantSearch({ - appId: customAppID, - apiKey: customApiKey, - indexName, - searchParameters, - urlSync: {}, - createAlgoliaClient, - }); - }); - - it('does not call algoliasearch directly', () => { - expect(algoliasearch.calledOnce).toBe(false, 'algoliasearch not called'); - }); - - it('calls createAlgoliaClient(appId, apiKey)', () => { - expect(createAlgoliaClient.calledOnce).toBe( - true, - 'clientInstanceFunction called once' - ); - expect(createAlgoliaClient.args[0]).toEqual([ - algoliasearch, - customAppID, - customApiKey, - ]); - }); - }); - describe('when adding a widget without render and init', () => { let widget; @@ -141,9 +98,8 @@ describe('InstantSearch lifecycle', () => { const disjunctiveFacetsRefinements = { fruits: ['apple'] }; const facetsRefinements = disjunctiveFacetsRefinements; search = new InstantSearch({ - appId, - apiKey, indexName, + searchClient: algoliasearch(appId, apiKey), searchParameters: { disjunctiveFacetsRefinements, facetsRefinements, @@ -376,9 +332,8 @@ describe('InstantSearch lifecycle', () => { beforeEach(() => { search = new InstantSearch({ - appId, - apiKey, indexName, + searchClient: algoliasearch(appId, apiKey), }); }); @@ -574,9 +529,8 @@ describe('InstantSearch lifecycle', () => { beforeEach(() => { search = new InstantSearch({ - appId, - apiKey, indexName, + searchClient: algoliasearch(appId, apiKey), }); }); @@ -624,9 +578,8 @@ describe('InstantSearch lifecycle', () => { it('should remove all widgets without triggering a search on dispose', () => { search = new InstantSearch({ - appId, - apiKey, indexName, + searchClient: algoliasearch(appId, apiKey), }); const widgets = times(5, () => ({ diff --git a/src/lib/__tests__/RoutingManager-test.js b/src/lib/__tests__/RoutingManager-test.js index 07bd0f4154..4339cb1dd4 100644 --- a/src/lib/__tests__/RoutingManager-test.js +++ b/src/lib/__tests__/RoutingManager-test.js @@ -1,19 +1,18 @@ +import algoliasearch from 'algoliasearch'; import instantsearch from '../main.js'; import RoutingManager from '../RoutingManager.js'; import simpleMapping from '../stateMappings/simple.js'; -const makeFakeAlgoliaClient = () => ({ +const fakeAlgoliaClient = { search: () => Promise.resolve({ results: [{}] }), -}); +}; describe('RoutingManager', () => { describe('getAllUIStates', () => { test('reads the state of widgets with a getWidgetState implementation', () => { const search = instantsearch({ - appId: '', - apiKey: '', indexName: '', - createAlgoliaClient: makeFakeAlgoliaClient, + searchClient: fakeAlgoliaClient, }); const widgetState = { @@ -56,10 +55,8 @@ describe('RoutingManager', () => { test('Does not read UI state from widgets without an implementation of getWidgetState', () => { const search = instantsearch({ - appId: '', - apiKey: '', indexName: '', - createAlgoliaClient: makeFakeAlgoliaClient, + searchClient: fakeAlgoliaClient, }); search.addWidget({ @@ -90,10 +87,8 @@ describe('RoutingManager', () => { describe('getAllSearchParameters', () => { test('should get searchParameters from widget that implements getWidgetSearchParameters', () => { const search = instantsearch({ - appId: '', - apiKey: '', indexName: '', - createAlgoliaClient: makeFakeAlgoliaClient, + searchClient: fakeAlgoliaClient, }); const widget = { @@ -133,10 +128,8 @@ describe('RoutingManager', () => { test('should not change the searchParameters if no widget has a getWidgetSearchParameters', () => { const search = instantsearch({ - appId: '', - apiKey: '', indexName: '', - createAlgoliaClient: makeFakeAlgoliaClient, + searchClient: fakeAlgoliaClient, }); const widget = { @@ -173,9 +166,11 @@ describe('RoutingManager', () => { }, }; const search = instantsearch({ - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', indexName: 'instant_search', + searchClient: algoliasearch( + 'latency', + '6be0576ff61c053d5f9a3225e2a90f76' + ), routing: { router, }, @@ -221,9 +216,11 @@ describe('RoutingManager', () => { }, }; const search = instantsearch({ - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', indexName: 'instant_search', + searchClient: algoliasearch( + 'latency', + '6be0576ff61c053d5f9a3225e2a90f76' + ), routing: { router, }, @@ -275,9 +272,11 @@ describe('RoutingManager', () => { }, }; const search = instantsearch({ - appId: 'latency', - apiKey: '6be0576ff61c053d5f9a3225e2a90f76', indexName: 'instant_search', + searchClient: algoliasearch( + 'latency', + '6be0576ff61c053d5f9a3225e2a90f76' + ), routing: { router, stateMapping, diff --git a/src/lib/__tests__/__snapshots__/InstantSearch-test.js.snap b/src/lib/__tests__/__snapshots__/InstantSearch-test.js.snap index 09bcd21de5..aabdae50ae 100644 --- a/src/lib/__tests__/__snapshots__/InstantSearch-test.js.snap +++ b/src/lib/__tests__/__snapshots__/InstantSearch-test.js.snap @@ -15,7 +15,7 @@ Array [ "_lastQueryIdReceived": -1, "_queryId": 0, "client": Object { - "algolia": "client", + "search": [Function], }, "derivedHelpers": Array [], "lastResults": null, @@ -87,7 +87,7 @@ Array [ "_searchStalledTimer": null, "_stalledSearchDelay": 200, "client": Object { - "algolia": "client", + "search": [Function], }, "domain": null, "helper": AlgoliaSearchHelper { @@ -101,7 +101,7 @@ Array [ "_lastQueryIdReceived": -1, "_queryId": 0, "client": Object { - "algolia": "client", + "search": [Function], }, "derivedHelpers": Array [], "lastResults": null, diff --git a/src/lib/__tests__/__snapshots__/search-client-test.js.snap b/src/lib/__tests__/__snapshots__/search-client-test.js.snap index caf480712a..4b04d6f6b0 100644 --- a/src/lib/__tests__/__snapshots__/search-client-test.js.snap +++ b/src/lib/__tests__/__snapshots__/search-client-test.js.snap @@ -28,4 +28,4 @@ Array [ ] `; -exports[`InstantSearch Search Client Properties throws if no \`search()\` method 1`] = `"InstantSearch configuration error: \`searchClient\` must implement a \`search(requests)\` method."`; +exports[`InstantSearch Search Client Properties throws if no \`search()\` method 1`] = `"The search client must implement a \`search(requests)\` method."`; diff --git a/src/lib/__tests__/api-collision.js b/src/lib/__tests__/api-collision.js deleted file mode 100644 index 960afdbe1e..0000000000 --- a/src/lib/__tests__/api-collision.js +++ /dev/null @@ -1,62 +0,0 @@ -/* eslint no-new: off */ -import InstantSearch from '../InstantSearch'; - -const usage = ` -Usage: instantsearch({ - indexName: 'my_index_name', - searchClient: algoliasearch('appId', 'apiKey') -});`; - -// THROWAWAY: Test suite to remove once the next major version is released -describe('InstantSearch API collision', () => { - describe('with search client', () => { - const appId = 'appId'; - const apiKey = 'apiKey'; - const indexName = 'indexName'; - const searchClient = { search() {} }; - - it('and indexName', () => { - expect(() => { - new InstantSearch({ - indexName, - searchClient, - }); - }).not.toThrow(); - }); - - it('and nothing else', () => { - expect(() => { - new InstantSearch({ - searchClient, - }); - }).toThrow(usage); - }); - - it('and appId', () => { - expect(() => { - new InstantSearch({ - appId, - searchClient, - }); - }).toThrow(usage); - }); - - it('and apiKey', () => { - expect(() => { - new InstantSearch({ - apiKey, - searchClient, - }); - }).toThrow(usage); - }); - - it('and createAlgoliaClient', () => { - expect(() => { - new InstantSearch({ - createAlgoliaClient: () => {}, - searchClient, - }); - }).toThrow(usage); - }); - }); -}); diff --git a/src/lib/main.js b/src/lib/main.js index 6581a0ae98..c2852bee4b 100644 --- a/src/lib/main.js +++ b/src/lib/main.js @@ -87,50 +87,12 @@ import * as stateMappings from './stateMappings/index.js'; /** * @typedef {Object} InstantSearchOptions - * @property {string} appId The Algolia application ID - * @property {string} apiKey The Algolia search-only API key * @property {string} indexName The name of the main index - * @property {string} [numberLocale] The locale used to display numbers. This will be passed - * to [`Number.prototype.toLocaleString()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString) - * @property {function} [searchFunction] A hook that will be called each time a search needs to be done, with the - * helper as a parameter. It's your responsibility to call `helper.search()`. This option allows you to avoid doing - * searches at page load for example. - * @property {function} [createAlgoliaClient] _Deprecated in favor of [`searchClient`](instantsearch.html#struct-InstantSearchOptions-searchClient)._ - * - * Allows you to provide your own algolia client instead of the one instantiated internally by instantsearch.js. - * Useful in situations where you need to setup complex mechanism on the client or if you need to share it easily. + * @property {SearchClient} searchClient The search client to plug to InstantSearch.js * * Usage: * ```javascript - * instantsearch({ - * // other parameters - * createAlgoliaClient: function(algoliasearch, appId, apiKey) { - * return anyCustomClient; - * } - * }); - * ``` - * We forward `algoliasearch`, which is the original [Algolia search client](https://www.algolia.com/doc/api-client/javascript/getting-started) imported inside InstantSearch.js - * @property {object} [searchParameters] Additional parameters to pass to - * the Algolia API ([see full documentation](https://community.algolia.com/algoliasearch-helper-js/reference.html#searchparameters)). - * @property {boolean|UrlSyncOptions} [urlSync] _Deprecated in favor of [`routing`](instantsearch.html#struct-InstantSearchOptions-routing)._ - * - * URL synchronization configuration. - * Setting to `true` will synchronize the needed search parameters with the browser URL. - * @property {number} [stalledSearchDelay=200] Time before a search is considered stalled. - * @property {RoutingOptions} [routing] Router configuration used to save the UI State into the URL or - * any client side persistence. - * @property {SearchClient} [searchClient] The search client to plug to InstantSearch.js. You should start updating with this - * syntax to ease the [migration to InstantSearch 3](./guides/prepare-for-v3.html). - * - * Usage: - * ```javascript - * // Using the default Algolia client (https://github.com/algolia/algoliasearch-client-javascript) - * // This is the default client used by InstantSearch. Equivalent to: - * // instantsearch({ - * // appId: 'appId', - * // apiKey: 'apiKey', - * // indexName: 'indexName', - * // }); + * // Using the default Algolia search client * instantsearch({ * indexName: 'indexName', * searchClient: algoliasearch('appId', 'apiKey') @@ -157,15 +119,31 @@ import * as stateMappings from './stateMappings/index.js'; * InstantSearch is the main component of InstantSearch.js. This object * manages the widget and lets you add new ones. * - * Three parameters are required to get you started with InstantSearch.js: - * - `appId`: your algolia application id - * - `apiKey`: the search key associated with your application + * Two parameters are required to get you started with InstantSearch.js: * - `indexName`: the main index that you will use for your new search UI + * - `searchClient`: the search client to plug to InstantSearch.js + * + * The [search client provided by Algolia](https://github.com/algolia/algoliasearch-client-javascript) + * needs an `appId` and an `apiKey`. Those parameters can be found in your + * [Algolia dashboard](https://www.algolia.com/api-keys). * - * Those parameters can be found in your [Algolia dashboard](https://www.algolia.com/api-keys). * If you want to get up and running quickly with InstantSearch.js, have a * look at the [getting started](getting-started.html). * + * @property {string} [numberLocale] The locale used to display numbers. This will be passed + * to [`Number.prototype.toLocaleString()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString) + * @property {function} [searchFunction] A hook that will be called each time a search needs to be done, with the + * helper as a parameter. It's your responsibility to call `helper.search()`. This option allows you to avoid doing + * searches at page load for example. + * @property {object} [searchParameters] Additional parameters to pass to + * the Algolia API ([see full documentation](https://community.algolia.com/algoliasearch-helper-js/reference.html#searchparameters)). + * @property {boolean|UrlSyncOptions} [urlSync] _Deprecated in favor of [`routing`](instantsearch.html#struct-InstantSearchOptions-routing)._ + * + * URL synchronization configuration. + * Setting to `true` will synchronize the needed search parameters with the browser URL. + * @property {number} [stalledSearchDelay=200] Time before a search is considered stalled. + * @property {RoutingOptions} [routing] Router configuration used to save the UI State into the URL or + * any client side persistence. * @function instantsearch * @param {InstantSearchOptions} $0 The options * @return {InstantSearch} the instantsearch instance diff --git a/src/widgets/sort-by/__tests__/sort-by-test.js b/src/widgets/sort-by/__tests__/sort-by-test.js index de4164cd99..9688963983 100644 --- a/src/widgets/sort-by/__tests__/sort-by-test.js +++ b/src/widgets/sort-by/__tests__/sort-by-test.js @@ -24,10 +24,10 @@ describe('sortBy()', () => { beforeEach(() => { const instantSearchInstance = instantSearch({ - apiKey: '', - appId: '', indexName: 'defaultIndex', - createAlgoliaClient: () => ({}), + searchClient: { + search() {}, + }, }); ReactDOM = { render: jest.fn() }; diff --git a/yarn.lock b/yarn.lock index df31e758c4..68cbecdc8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -197,9 +197,9 @@ algoliasearch-helper@2.26.0: qs "^6.5.1" util "^0.10.3" -algoliasearch@3.27.0: - version "3.27.0" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.27.0.tgz#675b7f2d186e5785a1553369b15d47b53d4efb31" +algoliasearch@3.30.0: + version "3.30.0" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.30.0.tgz#355585e49b672e5f71d45b9c2b371ecdff129cd1" dependencies: agentkeepalive "^2.2.0" debug "^2.6.8"