Skip to content

Commit

Permalink
feat(types): allow typed access to properties added to entry (algolia…
Browse files Browse the repository at this point in the history
…#4814)

also removes the file for "main" as it's inconsistent with index.es.ts
  • Loading branch information
Haroenv authored Aug 5, 2021
1 parent 362fb0f commit 9000f16
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 91 deletions.
2 changes: 1 addition & 1 deletion .storybook/decorators/withHits.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { action } from '@storybook/addon-actions';
import algoliasearch from 'algoliasearch/lite';
import instantsearch from '../../src/index';
import instantsearch from '../../src';
import defaultPlayground from '../playgrounds/default';
import { configure } from '../../src/widgets';
import { InstantSearch, InstantSearchOptions } from '../../src/types';
Expand Down
46 changes: 46 additions & 0 deletions src/__tests__/index-es-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import instantsearch from '../index.es';

describe('instantsearch()', () => {
it('includes a version', () => {
expect(instantsearch.version).toMatch(
/^(\d+\.)?(\d+\.)?(\*|\d+)(-beta.\d+)?$/
);
});

it('does not include the widget functions', () => {
// @ts-expect-error
expect(() => instantsearch.widgets).toThrowErrorMatchingInlineSnapshot(`
"\\"instantsearch.widgets\\" are not available from the ES build.
To import the widgets:
import { searchBox } from 'instantsearch.js/es/widgets'"
`);
});

it('does not include the connectors functions', () => {
// @ts-expect-error
expect(() => instantsearch.connectors).toThrowErrorMatchingInlineSnapshot(`
"\\"instantsearch.connectors\\" are not available from the ES build.
To import the connectors:
import { connectSearchBox } from 'instantsearch.js/es/connectors'"
`);
});

it('includes the helper functions', () => {
expect(Object.keys(instantsearch)).toMatchInlineSnapshot(`
Array [
"version",
"createInfiniteHitsSessionStorageCache",
"highlight",
"reverseHighlight",
"snippet",
"reverseSnippet",
"insights",
"getInsightsAnonymousUserToken",
]
`);
});
});
21 changes: 18 additions & 3 deletions src/lib/__tests__/main-test.ts → src/__tests__/index-test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import instantsearch from '../main';
import instantsearch from '..';

describe('instantsearch()', () => {
it('includes a version', () => {
Expand All @@ -19,7 +19,22 @@ describe('instantsearch()', () => {
});
});

it('includes the highlight helper function', () => {
expect(instantsearch.highlight).toBeInstanceOf(Function);
it('includes the API and the helper functions', () => {
expect(Object.keys(instantsearch)).toMatchInlineSnapshot(`
Array [
"version",
"connectors",
"widgets",
"middlewares",
"routers",
"stateMappings",
"createInfiniteHitsSessionStorageCache",
"highlight",
"reverseHighlight",
"snippet",
"reverseSnippet",
"insights",
]
`);
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import connectConfigureRelatedItems from '../connectConfigureRelatedItems';
import instantsearch from '../../../lib/main';
import instantsearch from '../../..';
import { createSearchClient } from '../../../../test/mock/createSearchClient';
import { AlgoliaHit } from '../../../types';
import { noop } from '../../../lib/utils';
Expand Down
2 changes: 1 addition & 1 deletion src/connectors/range/__tests__/connectRange-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import { createSearchClient } from '../../../../test/mock/createSearchClient';
import { createSingleSearchResponse } from '../../../../test/mock/createAPIResponse';
import { createInstantSearch } from '../../../../test/mock/createInstantSearch';
import instantsearch from '../../../lib/main';
import instantsearch from '../../..';

function createFacetStatsResults({
helper,
Expand Down
77 changes: 64 additions & 13 deletions src/index.es.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Expand, InstantSearchOptions, UiState } from './types';
import InstantSearch from './lib/InstantSearch';
import { Expand, UiState } from './types';
import InstantSearch, { InstantSearchOptions } from './lib/InstantSearch';
import version from './lib/version';
import {
snippet,
Expand All @@ -10,22 +10,73 @@ import {
getInsightsAnonymousUserToken,
} from './helpers';
import { createInfiniteHitsSessionStorageCache } from './lib/infiniteHitsCache';
import { deprecate } from './lib/utils';

const instantsearch = <
TUiState = Record<string, unknown>,
TRouteState = TUiState
>(
options: InstantSearchOptions<Expand<UiState & TUiState>, TRouteState>
) => new InstantSearch(options);
type InstantSearchModule = {
<TUiState = Record<string, unknown>, TRouteState = TUiState>(
options: InstantSearchOptions<Expand<UiState & TUiState>, TRouteState>
): InstantSearch<Expand<UiState & TUiState>, TRouteState>;
version: string;

// @major remove these in favour of the exports
/** @deprecated */
createInfiniteHitsSessionStorageCache: typeof createInfiniteHitsSessionStorageCache;
/** @deprecated */
highlight: typeof highlight;
/** @deprecated */
reverseHighlight: typeof reverseHighlight;
/** @deprecated */
snippet: typeof snippet;
/** @deprecated */
reverseSnippet: typeof reverseSnippet;
/** @deprecated */
insights: typeof insights;
/** @deprecated */
getInsightsAnonymousUserToken: typeof getInsightsAnonymousUserToken;
};

/**
* InstantSearch is the main component of InstantSearch.js. This object
* manages the widget and lets you add new ones.
*
* 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](algolia.com/doc/api-client/getting-started/what-is-the-api-client/javascript/)
* needs an `appId` and an `apiKey`. 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](https://www.algolia.com/doc/guides/building-search-ui/getting-started/js/).
*/
const instantsearch: InstantSearchModule = options =>
new InstantSearch(options);

instantsearch.version = version;
instantsearch.snippet = snippet;
instantsearch.reverseSnippet = reverseSnippet;
instantsearch.highlight = highlight;
instantsearch.reverseHighlight = reverseHighlight;

instantsearch.createInfiniteHitsSessionStorageCache = deprecate(
createInfiniteHitsSessionStorageCache,
"import { createInfiniteHitsSessionStorageCache } from 'instantsearch.js/es/helpers'"
);
instantsearch.highlight = deprecate(
highlight,
"import { highlight } from 'instantsearch.js/es/helpers'"
);
instantsearch.reverseHighlight = deprecate(
reverseHighlight,
"import { reverseHighlight } from 'instantsearch.js/es/helpers'"
);
instantsearch.snippet = deprecate(
snippet,
"import { snippet } from 'instantsearch.js/es/helpers'"
);
instantsearch.reverseSnippet = deprecate(
reverseSnippet,
"import { reverseSnippet } from 'instantsearch.js/es/helpers'"
);
instantsearch.insights = insights;
instantsearch.getInsightsAnonymousUserToken = getInsightsAnonymousUserToken;
instantsearch.createInfiniteHitsSessionStorageCache = createInfiniteHitsSessionStorageCache;

Object.defineProperty(instantsearch, 'widgets', {
get() {
Expand Down
69 changes: 68 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,70 @@
import instantsearch from './lib/main';
import InstantSearch, { InstantSearchOptions } from './lib/InstantSearch';
import { Expand, UiState } from './types';

import version from './lib/version';

import * as connectors from './connectors/index';
import * as widgets from './widgets/index';
import * as helpers from './helpers/index';
import * as middlewares from './middlewares/index';

import * as routers from './lib/routers/index';
import * as stateMappings from './lib/stateMappings/index';
import { createInfiniteHitsSessionStorageCache } from './lib/infiniteHitsCache/index';

type InstantSearchModule = {
<TUiState = Record<string, unknown>, TRouteState = TUiState>(
options: InstantSearchOptions<Expand<UiState & TUiState>, TRouteState>
): InstantSearch<Expand<UiState & TUiState>, TRouteState>;
version: string;

connectors: typeof connectors;
widgets: typeof widgets;
middlewares: typeof middlewares;

routers: typeof routers;
stateMappings: typeof stateMappings;

createInfiniteHitsSessionStorageCache: typeof createInfiniteHitsSessionStorageCache;
highlight: typeof helpers.highlight;
reverseHighlight: typeof helpers.reverseHighlight;
snippet: typeof helpers.snippet;
reverseSnippet: typeof helpers.reverseSnippet;
insights: typeof helpers.insights;
};

/**
* InstantSearch is the main component of InstantSearch.js. This object
* manages the widget and lets you add new ones.
*
* 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](algolia.com/doc/api-client/getting-started/what-is-the-api-client/javascript/)
* needs an `appId` and an `apiKey`. 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](https://www.algolia.com/doc/guides/building-search-ui/getting-started/js/).
*/
const instantsearch: InstantSearchModule = options =>
new InstantSearch(options);

instantsearch.version = version;

instantsearch.connectors = connectors;
instantsearch.widgets = widgets;
instantsearch.middlewares = middlewares;

instantsearch.routers = routers;
instantsearch.stateMappings = stateMappings;

instantsearch.createInfiniteHitsSessionStorageCache = createInfiniteHitsSessionStorageCache;
instantsearch.highlight = helpers.highlight;
instantsearch.reverseHighlight = helpers.reverseHighlight;
instantsearch.snippet = helpers.snippet;
instantsearch.reverseSnippet = helpers.reverseSnippet;
instantsearch.insights = helpers.insights;

export default instantsearch;
2 changes: 1 addition & 1 deletion src/lib/__tests__/RoutingManager-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
IndexUiState,
} from '../../types';
import historyRouter from '../routers/history';
import instantsearch from '../main';
import instantsearch from '../..';

const createFakeRouter = (args: Partial<Router> = {}): Router => ({
onUpdate(..._args) {},
Expand Down
52 changes: 0 additions & 52 deletions src/lib/main.ts

This file was deleted.

21 changes: 11 additions & 10 deletions src/lib/utils/__tests__/logger-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,29 @@ import { deprecate, warning } from '../logger';

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

it('expect to call initial function and print message', () => {
const warn = jest.spyOn(global.console, 'warn');
beforeEach(() => {
warn = jest.spyOn(global.console, 'warn');
warn.mockImplementation(() => {});
});

afterEach(() => {
warn.mockReset();
warn.mockRestore();
});

it('expect to call initial function and print message', () => {
const fn = deprecate(sum, 'message');

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

expect(actual).toBe(expectation);
expect(warn).toHaveBeenCalledWith('[InstantSearch.js]: message');

warn.mockReset();
warn.mockRestore();
});

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

const expectation0 = fn(1, 2, 3);
Expand All @@ -30,9 +34,6 @@ describe('deprecate', () => {
expect(actual).toBe(expectation0);
expect(actual).toBe(expectation1);
expect(warn).toHaveBeenCalledTimes(1);

warn.mockReset();
warn.mockRestore();
});
});

Expand Down
Loading

0 comments on commit 9000f16

Please sign in to comment.