Skip to content

Commit 9000f16

Browse files
authoredAug 5, 2021
feat(types): allow typed access to properties added to entry (#4814)
also removes the file for "main" as it's inconsistent with index.es.ts
1 parent 362fb0f commit 9000f16

File tree

12 files changed

+219
-91
lines changed

12 files changed

+219
-91
lines changed
 

‎.storybook/decorators/withHits.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { action } from '@storybook/addon-actions';
22
import algoliasearch from 'algoliasearch/lite';
3-
import instantsearch from '../../src/index';
3+
import instantsearch from '../../src';
44
import defaultPlayground from '../playgrounds/default';
55
import { configure } from '../../src/widgets';
66
import { InstantSearch, InstantSearchOptions } from '../../src/types';

‎src/__tests__/index-es-test.ts

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import instantsearch from '../index.es';
2+
3+
describe('instantsearch()', () => {
4+
it('includes a version', () => {
5+
expect(instantsearch.version).toMatch(
6+
/^(\d+\.)?(\d+\.)?(\*|\d+)(-beta.\d+)?$/
7+
);
8+
});
9+
10+
it('does not include the widget functions', () => {
11+
// @ts-expect-error
12+
expect(() => instantsearch.widgets).toThrowErrorMatchingInlineSnapshot(`
13+
"\\"instantsearch.widgets\\" are not available from the ES build.
14+
15+
To import the widgets:
16+
17+
import { searchBox } from 'instantsearch.js/es/widgets'"
18+
`);
19+
});
20+
21+
it('does not include the connectors functions', () => {
22+
// @ts-expect-error
23+
expect(() => instantsearch.connectors).toThrowErrorMatchingInlineSnapshot(`
24+
"\\"instantsearch.connectors\\" are not available from the ES build.
25+
26+
To import the connectors:
27+
28+
import { connectSearchBox } from 'instantsearch.js/es/connectors'"
29+
`);
30+
});
31+
32+
it('includes the helper functions', () => {
33+
expect(Object.keys(instantsearch)).toMatchInlineSnapshot(`
34+
Array [
35+
"version",
36+
"createInfiniteHitsSessionStorageCache",
37+
"highlight",
38+
"reverseHighlight",
39+
"snippet",
40+
"reverseSnippet",
41+
"insights",
42+
"getInsightsAnonymousUserToken",
43+
]
44+
`);
45+
});
46+
});

‎src/lib/__tests__/main-test.ts ‎src/__tests__/index-test.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import instantsearch from '../main';
1+
import instantsearch from '..';
22

33
describe('instantsearch()', () => {
44
it('includes a version', () => {
@@ -19,7 +19,22 @@ describe('instantsearch()', () => {
1919
});
2020
});
2121

22-
it('includes the highlight helper function', () => {
23-
expect(instantsearch.highlight).toBeInstanceOf(Function);
22+
it('includes the API and the helper functions', () => {
23+
expect(Object.keys(instantsearch)).toMatchInlineSnapshot(`
24+
Array [
25+
"version",
26+
"connectors",
27+
"widgets",
28+
"middlewares",
29+
"routers",
30+
"stateMappings",
31+
"createInfiniteHitsSessionStorageCache",
32+
"highlight",
33+
"reverseHighlight",
34+
"snippet",
35+
"reverseSnippet",
36+
"insights",
37+
]
38+
`);
2439
});
2540
});

‎src/connectors/configure-related-items/__tests__/connectConfigureRelatedItems-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import connectConfigureRelatedItems from '../connectConfigureRelatedItems';
2-
import instantsearch from '../../../lib/main';
2+
import instantsearch from '../../..';
33
import { createSearchClient } from '../../../../test/mock/createSearchClient';
44
import { AlgoliaHit } from '../../../types';
55
import { noop } from '../../../lib/utils';

‎src/connectors/range/__tests__/connectRange-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import { createSearchClient } from '../../../../test/mock/createSearchClient';
1313
import { createSingleSearchResponse } from '../../../../test/mock/createAPIResponse';
1414
import { createInstantSearch } from '../../../../test/mock/createInstantSearch';
15-
import instantsearch from '../../../lib/main';
15+
import instantsearch from '../../..';
1616

1717
function createFacetStatsResults({
1818
helper,

‎src/index.es.ts

+64-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Expand, InstantSearchOptions, UiState } from './types';
2-
import InstantSearch from './lib/InstantSearch';
1+
import { Expand, UiState } from './types';
2+
import InstantSearch, { InstantSearchOptions } from './lib/InstantSearch';
33
import version from './lib/version';
44
import {
55
snippet,
@@ -10,22 +10,73 @@ import {
1010
getInsightsAnonymousUserToken,
1111
} from './helpers';
1212
import { createInfiniteHitsSessionStorageCache } from './lib/infiniteHitsCache';
13+
import { deprecate } from './lib/utils';
1314

14-
const instantsearch = <
15-
TUiState = Record<string, unknown>,
16-
TRouteState = TUiState
17-
>(
18-
options: InstantSearchOptions<Expand<UiState & TUiState>, TRouteState>
19-
) => new InstantSearch(options);
15+
type InstantSearchModule = {
16+
<TUiState = Record<string, unknown>, TRouteState = TUiState>(
17+
options: InstantSearchOptions<Expand<UiState & TUiState>, TRouteState>
18+
): InstantSearch<Expand<UiState & TUiState>, TRouteState>;
19+
version: string;
20+
21+
// @major remove these in favour of the exports
22+
/** @deprecated */
23+
createInfiniteHitsSessionStorageCache: typeof createInfiniteHitsSessionStorageCache;
24+
/** @deprecated */
25+
highlight: typeof highlight;
26+
/** @deprecated */
27+
reverseHighlight: typeof reverseHighlight;
28+
/** @deprecated */
29+
snippet: typeof snippet;
30+
/** @deprecated */
31+
reverseSnippet: typeof reverseSnippet;
32+
/** @deprecated */
33+
insights: typeof insights;
34+
/** @deprecated */
35+
getInsightsAnonymousUserToken: typeof getInsightsAnonymousUserToken;
36+
};
37+
38+
/**
39+
* InstantSearch is the main component of InstantSearch.js. This object
40+
* manages the widget and lets you add new ones.
41+
*
42+
* Two parameters are required to get you started with InstantSearch.js:
43+
* - `indexName`: the main index that you will use for your new search UI
44+
* - `searchClient`: the search client to plug to InstantSearch.js
45+
*
46+
* The [search client provided by Algolia](algolia.com/doc/api-client/getting-started/what-is-the-api-client/javascript/)
47+
* needs an `appId` and an `apiKey`. Those parameters can be found in your
48+
* [Algolia dashboard](https://www.algolia.com/api-keys).
49+
*
50+
* If you want to get up and running quickly with InstantSearch.js, have a
51+
* look at the [getting started](https://www.algolia.com/doc/guides/building-search-ui/getting-started/js/).
52+
*/
53+
const instantsearch: InstantSearchModule = options =>
54+
new InstantSearch(options);
2055

2156
instantsearch.version = version;
22-
instantsearch.snippet = snippet;
23-
instantsearch.reverseSnippet = reverseSnippet;
24-
instantsearch.highlight = highlight;
25-
instantsearch.reverseHighlight = reverseHighlight;
57+
58+
instantsearch.createInfiniteHitsSessionStorageCache = deprecate(
59+
createInfiniteHitsSessionStorageCache,
60+
"import { createInfiniteHitsSessionStorageCache } from 'instantsearch.js/es/helpers'"
61+
);
62+
instantsearch.highlight = deprecate(
63+
highlight,
64+
"import { highlight } from 'instantsearch.js/es/helpers'"
65+
);
66+
instantsearch.reverseHighlight = deprecate(
67+
reverseHighlight,
68+
"import { reverseHighlight } from 'instantsearch.js/es/helpers'"
69+
);
70+
instantsearch.snippet = deprecate(
71+
snippet,
72+
"import { snippet } from 'instantsearch.js/es/helpers'"
73+
);
74+
instantsearch.reverseSnippet = deprecate(
75+
reverseSnippet,
76+
"import { reverseSnippet } from 'instantsearch.js/es/helpers'"
77+
);
2678
instantsearch.insights = insights;
2779
instantsearch.getInsightsAnonymousUserToken = getInsightsAnonymousUserToken;
28-
instantsearch.createInfiniteHitsSessionStorageCache = createInfiniteHitsSessionStorageCache;
2980

3081
Object.defineProperty(instantsearch, 'widgets', {
3182
get() {

‎src/index.ts

+68-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,70 @@
1-
import instantsearch from './lib/main';
1+
import InstantSearch, { InstantSearchOptions } from './lib/InstantSearch';
2+
import { Expand, UiState } from './types';
3+
4+
import version from './lib/version';
5+
6+
import * as connectors from './connectors/index';
7+
import * as widgets from './widgets/index';
8+
import * as helpers from './helpers/index';
9+
import * as middlewares from './middlewares/index';
10+
11+
import * as routers from './lib/routers/index';
12+
import * as stateMappings from './lib/stateMappings/index';
13+
import { createInfiniteHitsSessionStorageCache } from './lib/infiniteHitsCache/index';
14+
15+
type InstantSearchModule = {
16+
<TUiState = Record<string, unknown>, TRouteState = TUiState>(
17+
options: InstantSearchOptions<Expand<UiState & TUiState>, TRouteState>
18+
): InstantSearch<Expand<UiState & TUiState>, TRouteState>;
19+
version: string;
20+
21+
connectors: typeof connectors;
22+
widgets: typeof widgets;
23+
middlewares: typeof middlewares;
24+
25+
routers: typeof routers;
26+
stateMappings: typeof stateMappings;
27+
28+
createInfiniteHitsSessionStorageCache: typeof createInfiniteHitsSessionStorageCache;
29+
highlight: typeof helpers.highlight;
30+
reverseHighlight: typeof helpers.reverseHighlight;
31+
snippet: typeof helpers.snippet;
32+
reverseSnippet: typeof helpers.reverseSnippet;
33+
insights: typeof helpers.insights;
34+
};
35+
36+
/**
37+
* InstantSearch is the main component of InstantSearch.js. This object
38+
* manages the widget and lets you add new ones.
39+
*
40+
* Two parameters are required to get you started with InstantSearch.js:
41+
* - `indexName`: the main index that you will use for your new search UI
42+
* - `searchClient`: the search client to plug to InstantSearch.js
43+
*
44+
* The [search client provided by Algolia](algolia.com/doc/api-client/getting-started/what-is-the-api-client/javascript/)
45+
* needs an `appId` and an `apiKey`. Those parameters can be found in your
46+
* [Algolia dashboard](https://www.algolia.com/api-keys).
47+
*
48+
* If you want to get up and running quickly with InstantSearch.js, have a
49+
* look at the [getting started](https://www.algolia.com/doc/guides/building-search-ui/getting-started/js/).
50+
*/
51+
const instantsearch: InstantSearchModule = options =>
52+
new InstantSearch(options);
53+
54+
instantsearch.version = version;
55+
56+
instantsearch.connectors = connectors;
57+
instantsearch.widgets = widgets;
58+
instantsearch.middlewares = middlewares;
59+
60+
instantsearch.routers = routers;
61+
instantsearch.stateMappings = stateMappings;
62+
63+
instantsearch.createInfiniteHitsSessionStorageCache = createInfiniteHitsSessionStorageCache;
64+
instantsearch.highlight = helpers.highlight;
65+
instantsearch.reverseHighlight = helpers.reverseHighlight;
66+
instantsearch.snippet = helpers.snippet;
67+
instantsearch.reverseSnippet = helpers.reverseSnippet;
68+
instantsearch.insights = helpers.insights;
269

370
export default instantsearch;

‎src/lib/__tests__/RoutingManager-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
IndexUiState,
1313
} from '../../types';
1414
import historyRouter from '../routers/history';
15-
import instantsearch from '../main';
15+
import instantsearch from '../..';
1616

1717
const createFakeRouter = (args: Partial<Router> = {}): Router => ({
1818
onUpdate(..._args) {},

‎src/lib/main.ts

-52
This file was deleted.

‎src/lib/utils/__tests__/logger-test.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,29 @@ import { deprecate, warning } from '../logger';
22

33
describe('deprecate', () => {
44
const sum = (...args: number[]) => args.reduce((acc, _) => acc + _, 0);
5+
let warn: jest.SpiedFunction<typeof global.console.warn>;
56

6-
it('expect to call initial function and print message', () => {
7-
const warn = jest.spyOn(global.console, 'warn');
7+
beforeEach(() => {
8+
warn = jest.spyOn(global.console, 'warn');
89
warn.mockImplementation(() => {});
10+
});
11+
12+
afterEach(() => {
13+
warn.mockReset();
14+
warn.mockRestore();
15+
});
16+
17+
it('expect to call initial function and print message', () => {
918
const fn = deprecate(sum, 'message');
1019

1120
const expectation = fn(1, 2, 3);
1221
const actual = 6;
1322

1423
expect(actual).toBe(expectation);
1524
expect(warn).toHaveBeenCalledWith('[InstantSearch.js]: message');
16-
17-
warn.mockReset();
18-
warn.mockRestore();
1925
});
2026

2127
it('expect to call initial function twice and print message once', () => {
22-
const warn = jest.spyOn(global.console, 'warn');
23-
warn.mockImplementation(() => {});
2428
const fn = deprecate(sum, 'message');
2529

2630
const expectation0 = fn(1, 2, 3);
@@ -30,9 +34,6 @@ describe('deprecate', () => {
3034
expect(actual).toBe(expectation0);
3135
expect(actual).toBe(expectation1);
3236
expect(warn).toHaveBeenCalledTimes(1);
33-
34-
warn.mockReset();
35-
warn.mockRestore();
3637
});
3738
});
3839

‎src/lib/utils/logger.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import noop from './noop';
22

3-
type Deprecate<TCallback = (...args: any[]) => any> = (
4-
fn: TCallback,
5-
message: string
6-
) => TCallback;
7-
83
type Warn = (message: string) => void;
94

105
type Warning = {
@@ -15,7 +10,12 @@ type Warning = {
1510
/**
1611
* Logs a warning when this function is called, in development environment only.
1712
*/
18-
let deprecate: Deprecate = fn => fn;
13+
let deprecate = <TCallback extends (...args: any[]) => any>(
14+
fn: TCallback,
15+
// @ts-ignore this parameter is used in the __DEV__ branch
16+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
17+
message: string
18+
) => fn;
1919

2020
/**
2121
* Logs a warning
@@ -46,7 +46,7 @@ if (__DEV__) {
4646
}
4747

4848
return fn(...args);
49-
};
49+
} as typeof fn;
5050
};
5151

5252
warning = ((condition, message) => {

‎src/middlewares/__tests__/createMetadataMiddleware.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import algoliasearchV3 from 'algoliasearch-v3';
44
import { createMetadataMiddleware } from '..';
55
import { createSearchClient } from '../../../test/mock/createSearchClient';
66
import { wait } from '../../../test/utils/wait';
7-
import instantsearch from '../../lib/main';
7+
import instantsearch from '../..';
88
import { configure, hits, index, pagination, searchBox } from '../../widgets';
99
import { isMetadataEnabled } from '../createMetadataMiddleware';
1010

0 commit comments

Comments
 (0)
Please sign in to comment.