vue-instantsearch 4.1.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/package.json +5 -5
- package/src/components/DynamicWidgets.js +1 -1
- package/src/components/ExperimentalDynamicWidgets.js +10 -0
- package/src/components/__tests__/ExperimentalDynamicWidgets.js +41 -0
- package/src/mixins/widget.js +1 -1
- package/src/util/__tests__/createServerRootMixin.test.js +141 -61
- package/src/util/createServerRootMixin.js +36 -107
- package/src/util/testutils/helper.js +2 -2
- package/src/widgets.js +3 -0
- package/vue2/cjs/index.js +1 -1
- package/vue2/cjs/index.js.map +1 -1
- package/vue2/es/package.json.js +1 -1
- package/vue2/es/src/components/DynamicWidgets.js +1 -1
- package/vue2/es/src/components/DynamicWidgets.js.map +1 -1
- package/vue2/es/src/components/ExperimentalDynamicWidgets.js +2 -0
- package/vue2/es/src/components/ExperimentalDynamicWidgets.js.map +1 -0
- package/vue2/es/src/instantsearch.js +1 -1
- package/vue2/es/src/mixins/widget.js +1 -1
- package/vue2/es/src/mixins/widget.js.map +1 -1
- package/vue2/es/src/util/createServerRootMixin.js +1 -1
- package/vue2/es/src/util/createServerRootMixin.js.map +1 -1
- package/vue2/es/src/widgets.js +1 -1
- package/vue2/umd/index.js +1 -1
- package/vue2/umd/index.js.map +1 -1
- package/vue3/cjs/index.js +1 -1
- package/vue3/cjs/index.js.map +1 -1
- package/vue3/es/package.json.js +1 -1
- package/vue3/es/src/components/DynamicWidgets.js +1 -1
- package/vue3/es/src/components/DynamicWidgets.js.map +1 -1
- package/vue3/es/src/components/ExperimentalDynamicWidgets.js +2 -0
- package/vue3/es/src/components/ExperimentalDynamicWidgets.js.map +1 -0
- package/vue3/es/src/instantsearch.js +1 -1
- package/vue3/es/src/mixins/widget.js +1 -1
- package/vue3/es/src/mixins/widget.js.map +1 -1
- package/vue3/es/src/util/createServerRootMixin.js +1 -1
- package/vue3/es/src/util/createServerRootMixin.js.map +1 -1
- package/vue3/es/src/widgets.js +1 -1
- package/vue3/umd/index.js +1 -1
- package/vue3/umd/index.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
# [4.2.0](https://github.com/algolia/vue-instantsearch/compare/v4.1.1...v4.2.0) (2021-12-13)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **dynamicWidgets:** release as production ([#1086](https://github.com/algolia/vue-instantsearch/issues/1086)) ([9e0902b](https://github.com/algolia/vue-instantsearch/commit/9e0902bc7a3afe3eb2211b78e681e65b3677dd78))
|
|
7
|
+
* **instantsearch:** update version ([dbf485f](https://github.com/algolia/vue-instantsearch/commit/dbf485f6263d9821aaf169e682ff1ab94157d15f))
|
|
8
|
+
* **ssr:** prevent initial network request ([#1090](https://github.com/algolia/vue-instantsearch/issues/1090)) ([d97eea2](https://github.com/algolia/vue-instantsearch/commit/d97eea21fbd059b0ca0634a6984a6a8b02acdd3d))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
1
12
|
## [4.1.1](https://github.com/algolia/vue-instantsearch/compare/v4.1.0...v4.1.1) (2021-10-27)
|
|
2
13
|
|
|
3
14
|
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"autocomplete"
|
|
17
17
|
],
|
|
18
18
|
"license": "MIT",
|
|
19
|
-
"version": "4.
|
|
19
|
+
"version": "4.2.0",
|
|
20
20
|
"files": [
|
|
21
21
|
"vue2",
|
|
22
22
|
"vue3",
|
|
@@ -48,8 +48,7 @@
|
|
|
48
48
|
"release": "shipjs prepare"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"
|
|
52
|
-
"instantsearch.js": "^4.32.0",
|
|
51
|
+
"instantsearch.js": "^4.35.0",
|
|
53
52
|
"mitt": "^2.1.0"
|
|
54
53
|
},
|
|
55
54
|
"peerDependencies": {
|
|
@@ -82,6 +81,7 @@
|
|
|
82
81
|
"@wdio/spec-reporter": "^5.11.7",
|
|
83
82
|
"@wdio/static-server-service": "^5.11.0",
|
|
84
83
|
"algoliasearch": "4.0.1",
|
|
84
|
+
"algoliasearch-helper": "3.7.0",
|
|
85
85
|
"babel-eslint": "10.0.1",
|
|
86
86
|
"babel-jest": "23.6.0",
|
|
87
87
|
"babel-preset-es2015": "6.24.1",
|
|
@@ -132,11 +132,11 @@
|
|
|
132
132
|
"bundlesize": [
|
|
133
133
|
{
|
|
134
134
|
"path": "./vue2/umd/index.js",
|
|
135
|
-
"maxSize": "
|
|
135
|
+
"maxSize": "56.00 kB"
|
|
136
136
|
},
|
|
137
137
|
{
|
|
138
138
|
"path": "./vue3/umd/index.js",
|
|
139
|
-
"maxSize": "
|
|
139
|
+
"maxSize": "57.00 kB"
|
|
140
140
|
},
|
|
141
141
|
{
|
|
142
142
|
"path": "./vue2/cjs/index.js",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import AisDynamicWidgets from './DynamicWidgets';
|
|
2
|
+
import { warn } from '../util/warn';
|
|
3
|
+
|
|
4
|
+
// @MAJOR remove this file
|
|
5
|
+
export default Object.assign({}, AisDynamicWidgets, {
|
|
6
|
+
name: 'AisExperimentalDynamicWidgets',
|
|
7
|
+
mounted() {
|
|
8
|
+
warn('Use AisDynamicWidgets instead of AisExperimentalDynamicWidgets.');
|
|
9
|
+
},
|
|
10
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { mount } from '../../../test/utils';
|
|
2
|
+
import ExperimentalDynamicWidgets from '../ExperimentalDynamicWidgets';
|
|
3
|
+
import { warn } from '../../util/warn';
|
|
4
|
+
import { __setState } from '../../mixins/widget';
|
|
5
|
+
import DynamicWidgets from '../DynamicWidgets';
|
|
6
|
+
|
|
7
|
+
jest.mock('../../mixins/widget');
|
|
8
|
+
jest.mock('../../util/warn', () => ({ warn: jest.fn() }));
|
|
9
|
+
|
|
10
|
+
it('warns on mount', () => {
|
|
11
|
+
__setState(null);
|
|
12
|
+
|
|
13
|
+
mount({
|
|
14
|
+
template: '<ExperimentalDynamicWidgets />',
|
|
15
|
+
components: {
|
|
16
|
+
ExperimentalDynamicWidgets,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
expect(warn).toHaveBeenCalledTimes(1);
|
|
20
|
+
expect(warn.mock.calls[0][0]).toMatchInlineSnapshot(
|
|
21
|
+
`"Use AisDynamicWidgets instead of AisExperimentalDynamicWidgets."`
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('behaves the same as DynamicWidgets', () => {
|
|
26
|
+
Object.keys(ExperimentalDynamicWidgets).forEach(key => {
|
|
27
|
+
if (key === 'name') {
|
|
28
|
+
// name is different
|
|
29
|
+
expect(ExperimentalDynamicWidgets[key]).toBe(
|
|
30
|
+
'AisExperimentalDynamicWidgets'
|
|
31
|
+
);
|
|
32
|
+
} else if (key === 'mounted') {
|
|
33
|
+
// mounted has the warning
|
|
34
|
+
expect(ExperimentalDynamicWidgets[key]).toEqual(expect.any(Function));
|
|
35
|
+
} else if (key[0] === '_') {
|
|
36
|
+
// private Vue behavior, not tested
|
|
37
|
+
} else {
|
|
38
|
+
expect(ExperimentalDynamicWidgets[key]).toEqual(DynamicWidgets[key]);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
package/src/mixins/widget.js
CHANGED
|
@@ -31,7 +31,7 @@ export const createWidgetMixin = ({ connector } = {}) => ({
|
|
|
31
31
|
this.getParentIndex().addWidgets([this.widget]);
|
|
32
32
|
|
|
33
33
|
if (
|
|
34
|
-
this.instantSearchInstance.
|
|
34
|
+
this.instantSearchInstance._initialResults &&
|
|
35
35
|
!this.instantSearchInstance.started
|
|
36
36
|
) {
|
|
37
37
|
if (typeof this.instantSearchInstance.__forceRender !== 'function') {
|
|
@@ -11,9 +11,9 @@ import { createFakeClient } from '../testutils/client';
|
|
|
11
11
|
import { createSerializedState } from '../testutils/helper';
|
|
12
12
|
import { isVue3, isVue2, Vue2, renderCompat } from '../vue-compat';
|
|
13
13
|
import {
|
|
14
|
-
SearchResults,
|
|
15
|
-
SearchParameters,
|
|
16
14
|
AlgoliaSearchHelper,
|
|
15
|
+
SearchParameters,
|
|
16
|
+
SearchResults,
|
|
17
17
|
} from 'algoliasearch-helper';
|
|
18
18
|
|
|
19
19
|
jest.unmock('instantsearch.js/es');
|
|
@@ -57,9 +57,11 @@ describe('createServerRootMixin', () => {
|
|
|
57
57
|
}),
|
|
58
58
|
],
|
|
59
59
|
})
|
|
60
|
-
).toThrowErrorMatchingInlineSnapshot(
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
61
|
+
"The \`searchClient\` option is required.
|
|
62
|
+
|
|
63
|
+
See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsearch/js/"
|
|
64
|
+
`);
|
|
63
65
|
});
|
|
64
66
|
|
|
65
67
|
it('requires indexName', () => {
|
|
@@ -72,9 +74,11 @@ describe('createServerRootMixin', () => {
|
|
|
72
74
|
}),
|
|
73
75
|
],
|
|
74
76
|
})
|
|
75
|
-
).toThrowErrorMatchingInlineSnapshot(
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
78
|
+
"The \`indexName\` option is required.
|
|
79
|
+
|
|
80
|
+
See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsearch/js/"
|
|
81
|
+
`);
|
|
78
82
|
});
|
|
79
83
|
|
|
80
84
|
it('creates an instantsearch instance on "data"', () => {
|
|
@@ -301,14 +305,13 @@ Array [
|
|
|
301
305
|
renderToString,
|
|
302
306
|
});
|
|
303
307
|
expect(state).toEqual({
|
|
304
|
-
__identifier: 'stringified',
|
|
305
308
|
hello: {
|
|
306
|
-
|
|
309
|
+
results: [
|
|
307
310
|
{
|
|
308
311
|
query: '',
|
|
309
312
|
},
|
|
310
313
|
],
|
|
311
|
-
|
|
314
|
+
state: {
|
|
312
315
|
disjunctiveFacets: [],
|
|
313
316
|
disjunctiveFacetsRefinements: {},
|
|
314
317
|
facets: [],
|
|
@@ -534,7 +537,7 @@ Array [
|
|
|
534
537
|
this.instantsearch.mainIndex.getWidgets().map(w => w.$$type)
|
|
535
538
|
).toEqual(['ais.configure']);
|
|
536
539
|
|
|
537
|
-
expect(res.hello.
|
|
540
|
+
expect(res.hello.state.hitsPerPage).toBe(100);
|
|
538
541
|
})
|
|
539
542
|
// jest throws an error we need to catch, since stuck in the flow
|
|
540
543
|
.catch(e => {
|
|
@@ -656,11 +659,73 @@ Array [
|
|
|
656
659
|
|
|
657
660
|
await renderToString(wrapper);
|
|
658
661
|
});
|
|
662
|
+
|
|
663
|
+
it('searches only once', async () => {
|
|
664
|
+
const searchClient = createFakeClient();
|
|
665
|
+
const app = {
|
|
666
|
+
mixins: [
|
|
667
|
+
forceIsServerMixin,
|
|
668
|
+
createServerRootMixin({
|
|
669
|
+
searchClient,
|
|
670
|
+
indexName: 'hello',
|
|
671
|
+
}),
|
|
672
|
+
],
|
|
673
|
+
render: renderCompat(h =>
|
|
674
|
+
/**
|
|
675
|
+
* This code triggers this warning in Vue 3:
|
|
676
|
+
* > Non-function value encountered for default slot. Prefer function slots for better performance.
|
|
677
|
+
*
|
|
678
|
+
* To fix it, replace the third argument
|
|
679
|
+
* > [h(...), h(...)]
|
|
680
|
+
* with
|
|
681
|
+
* > { default: () => [h(...), h(...)] }
|
|
682
|
+
*
|
|
683
|
+
* but it's not important (and not compatible in vue2), we're leaving it as-is.
|
|
684
|
+
*/
|
|
685
|
+
h(InstantSearchSsr, {}, [
|
|
686
|
+
h(Configure, {
|
|
687
|
+
attrs: {
|
|
688
|
+
hitsPerPage: 100,
|
|
689
|
+
},
|
|
690
|
+
}),
|
|
691
|
+
h(SearchBox),
|
|
692
|
+
])
|
|
693
|
+
),
|
|
694
|
+
serverPrefetch() {
|
|
695
|
+
return this.instantsearch.findResultsState({
|
|
696
|
+
component: this,
|
|
697
|
+
renderToString,
|
|
698
|
+
});
|
|
699
|
+
},
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
const wrapper = createSSRApp({
|
|
703
|
+
mixins: [forceIsServerMixin],
|
|
704
|
+
render: renderCompat(h => h(app)),
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
await renderToString(wrapper);
|
|
708
|
+
|
|
709
|
+
expect(searchClient.search).toHaveBeenCalledTimes(1);
|
|
710
|
+
expect(searchClient.search.mock.calls[0][0]).toMatchInlineSnapshot(`
|
|
711
|
+
Array [
|
|
712
|
+
Object {
|
|
713
|
+
"indexName": "hello",
|
|
714
|
+
"params": Object {
|
|
715
|
+
"facets": Array [],
|
|
716
|
+
"hitsPerPage": 100,
|
|
717
|
+
"query": "",
|
|
718
|
+
"tagFilters": "",
|
|
719
|
+
},
|
|
720
|
+
},
|
|
721
|
+
]
|
|
722
|
+
`);
|
|
723
|
+
});
|
|
659
724
|
}
|
|
660
725
|
});
|
|
661
726
|
|
|
662
727
|
describe('hydrate', () => {
|
|
663
|
-
it('sets
|
|
728
|
+
it('sets _initialResults', () => {
|
|
664
729
|
const serialized = createSerializedState();
|
|
665
730
|
|
|
666
731
|
const app = {
|
|
@@ -683,7 +748,6 @@ Array [
|
|
|
683
748
|
// in test, beforeCreated doesn't have $data yet, but IRL it does
|
|
684
749
|
created() {
|
|
685
750
|
this.instantsearch.hydrate({
|
|
686
|
-
__identifier: 'stringified',
|
|
687
751
|
hello: serialized,
|
|
688
752
|
});
|
|
689
753
|
},
|
|
@@ -693,57 +757,20 @@ Array [
|
|
|
693
757
|
vm: { instantsearch },
|
|
694
758
|
} = mount(app);
|
|
695
759
|
|
|
696
|
-
expect(instantsearch.
|
|
697
|
-
expect.objectContaining({
|
|
760
|
+
expect(instantsearch._initialResults).toEqual(
|
|
761
|
+
expect.objectContaining({
|
|
762
|
+
hello: {
|
|
763
|
+
state: expect.any(Object),
|
|
764
|
+
results: expect.any(Object),
|
|
765
|
+
},
|
|
766
|
+
})
|
|
698
767
|
);
|
|
699
768
|
|
|
700
|
-
expect(instantsearch.
|
|
769
|
+
expect(instantsearch._initialResults.hello).toEqual(
|
|
701
770
|
expect.objectContaining(serialized)
|
|
702
771
|
);
|
|
703
772
|
});
|
|
704
773
|
|
|
705
|
-
it('accepts non-stringified results', () => {
|
|
706
|
-
const serialized = createSerializedState();
|
|
707
|
-
const nonSerialized = new SearchResults(
|
|
708
|
-
new SearchParameters(serialized._state),
|
|
709
|
-
serialized._rawResults
|
|
710
|
-
);
|
|
711
|
-
|
|
712
|
-
const app = {
|
|
713
|
-
mixins: [
|
|
714
|
-
createServerRootMixin({
|
|
715
|
-
searchClient: createFakeClient(),
|
|
716
|
-
indexName: 'movies',
|
|
717
|
-
}),
|
|
718
|
-
],
|
|
719
|
-
render: renderCompat(h =>
|
|
720
|
-
h(InstantSearchSsr, {}, [
|
|
721
|
-
h(Configure, {
|
|
722
|
-
attrs: {
|
|
723
|
-
hitsPerPage: 100,
|
|
724
|
-
},
|
|
725
|
-
}),
|
|
726
|
-
h(SearchBox),
|
|
727
|
-
])
|
|
728
|
-
),
|
|
729
|
-
created() {
|
|
730
|
-
this.instantsearch.hydrate({
|
|
731
|
-
movies: nonSerialized,
|
|
732
|
-
});
|
|
733
|
-
|
|
734
|
-
expect(this.instantsearch.__initialSearchResults).toEqual(
|
|
735
|
-
expect.objectContaining({ movies: expect.any(SearchResults) })
|
|
736
|
-
);
|
|
737
|
-
|
|
738
|
-
expect(this.instantsearch.__initialSearchResults.movies).toEqual(
|
|
739
|
-
nonSerialized
|
|
740
|
-
);
|
|
741
|
-
},
|
|
742
|
-
};
|
|
743
|
-
|
|
744
|
-
mount(app);
|
|
745
|
-
});
|
|
746
|
-
|
|
747
774
|
it('inits the main index', () => {
|
|
748
775
|
const serialized = createSerializedState();
|
|
749
776
|
|
|
@@ -773,7 +800,6 @@ Array [
|
|
|
773
800
|
expect(instantsearch.mainIndex.getHelper()).toBe(null);
|
|
774
801
|
|
|
775
802
|
instantsearch.hydrate({
|
|
776
|
-
__identifier: 'stringified',
|
|
777
803
|
hello: serialized,
|
|
778
804
|
});
|
|
779
805
|
|
|
@@ -812,7 +838,6 @@ Array [
|
|
|
812
838
|
expect(instantsearch.mainHelper).toBe(null);
|
|
813
839
|
|
|
814
840
|
instantsearch.hydrate({
|
|
815
|
-
__identifier: 'stringified',
|
|
816
841
|
hello: serialized,
|
|
817
842
|
});
|
|
818
843
|
|
|
@@ -834,6 +859,7 @@ Array [
|
|
|
834
859
|
created() {
|
|
835
860
|
instantSearchInstance = this.instantsearch;
|
|
836
861
|
},
|
|
862
|
+
render() {},
|
|
837
863
|
});
|
|
838
864
|
|
|
839
865
|
const widget = {
|
|
@@ -894,6 +920,58 @@ Object {
|
|
|
894
920
|
);
|
|
895
921
|
});
|
|
896
922
|
|
|
923
|
+
it('uses the results passed to hydrate for rendering', () => {
|
|
924
|
+
let instantSearchInstance;
|
|
925
|
+
mount({
|
|
926
|
+
mixins: [
|
|
927
|
+
createServerRootMixin({
|
|
928
|
+
searchClient: createFakeClient(),
|
|
929
|
+
indexName: 'lol',
|
|
930
|
+
}),
|
|
931
|
+
],
|
|
932
|
+
created() {
|
|
933
|
+
instantSearchInstance = this.instantsearch;
|
|
934
|
+
},
|
|
935
|
+
render() {},
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
const widget = {
|
|
939
|
+
init: jest.fn(),
|
|
940
|
+
render: jest.fn(),
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
const resultsState = createSerializedState();
|
|
944
|
+
const state = new SearchParameters(resultsState.state);
|
|
945
|
+
const results = new SearchResults(state, resultsState.results);
|
|
946
|
+
|
|
947
|
+
instantSearchInstance.hydrate({
|
|
948
|
+
lol: resultsState,
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
instantSearchInstance.__forceRender(
|
|
952
|
+
widget,
|
|
953
|
+
instantSearchInstance.mainIndex
|
|
954
|
+
);
|
|
955
|
+
|
|
956
|
+
expect(widget.init).toHaveBeenCalledTimes(0);
|
|
957
|
+
expect(widget.render).toHaveBeenCalledTimes(1);
|
|
958
|
+
|
|
959
|
+
const renderArgs = widget.render.mock.calls[0][0];
|
|
960
|
+
|
|
961
|
+
expect(renderArgs).toEqual(
|
|
962
|
+
expect.objectContaining({
|
|
963
|
+
state,
|
|
964
|
+
results,
|
|
965
|
+
scopedResults: [
|
|
966
|
+
expect.objectContaining({
|
|
967
|
+
indexId: 'lol',
|
|
968
|
+
results,
|
|
969
|
+
}),
|
|
970
|
+
],
|
|
971
|
+
})
|
|
972
|
+
);
|
|
973
|
+
});
|
|
974
|
+
|
|
897
975
|
describe('createURL', () => {
|
|
898
976
|
it('returns # if instantsearch has no routing', () => {
|
|
899
977
|
let instantSearchInstance;
|
|
@@ -907,6 +985,7 @@ Object {
|
|
|
907
985
|
created() {
|
|
908
986
|
instantSearchInstance = this.instantsearch;
|
|
909
987
|
},
|
|
988
|
+
render() {},
|
|
910
989
|
});
|
|
911
990
|
|
|
912
991
|
const widget = {
|
|
@@ -940,6 +1019,7 @@ Object {
|
|
|
940
1019
|
created() {
|
|
941
1020
|
instantSearchInstance = this.instantsearch;
|
|
942
1021
|
},
|
|
1022
|
+
render() {},
|
|
943
1023
|
});
|
|
944
1024
|
|
|
945
1025
|
const widget = {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import instantsearch from 'instantsearch.js/es';
|
|
2
|
-
import algoliaHelper from 'algoliasearch-helper';
|
|
3
2
|
import { isVue3, isVue2, Vue2, createSSRApp } from '../util/vue-compat';
|
|
4
|
-
const { SearchResults, SearchParameters } = algoliaHelper;
|
|
5
3
|
import { warn } from './warn';
|
|
6
4
|
|
|
7
5
|
function walkIndex(indexWidget, visit) {
|
|
@@ -76,18 +74,10 @@ function defaultCloneComponent(componentInstance, { mixins = [] } = {}) {
|
|
|
76
74
|
return app;
|
|
77
75
|
}
|
|
78
76
|
|
|
79
|
-
function augmentInstantSearch(
|
|
80
|
-
instantSearchOptions,
|
|
81
|
-
searchClient,
|
|
82
|
-
indexName,
|
|
83
|
-
cloneComponent
|
|
84
|
-
) {
|
|
85
|
-
/* eslint-disable no-param-reassign */
|
|
86
|
-
|
|
87
|
-
const helper = algoliaHelper(searchClient, indexName);
|
|
77
|
+
function augmentInstantSearch(instantSearchOptions, cloneComponent) {
|
|
88
78
|
const search = instantsearch(instantSearchOptions);
|
|
89
79
|
|
|
90
|
-
let
|
|
80
|
+
let initialResults;
|
|
91
81
|
|
|
92
82
|
/**
|
|
93
83
|
* main API for SSR, called in serverPrefetch of a root component which contains instantsearch
|
|
@@ -104,7 +94,7 @@ function augmentInstantSearch(
|
|
|
104
94
|
}
|
|
105
95
|
|
|
106
96
|
let app;
|
|
107
|
-
let
|
|
97
|
+
let instance;
|
|
108
98
|
|
|
109
99
|
return Promise.resolve()
|
|
110
100
|
.then(() => {
|
|
@@ -112,55 +102,36 @@ function augmentInstantSearch(
|
|
|
112
102
|
mixins: [
|
|
113
103
|
{
|
|
114
104
|
created() {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
instantSearchInstance: this.instantsearch,
|
|
122
|
-
parent: null,
|
|
123
|
-
uiState: this.instantsearch._initialUiState,
|
|
124
|
-
});
|
|
105
|
+
instance = this.instantsearch;
|
|
106
|
+
|
|
107
|
+
instance.start();
|
|
108
|
+
// although we use start for initializing the main index,
|
|
109
|
+
// we don't want to send search requests yet
|
|
110
|
+
instance.started = false;
|
|
125
111
|
},
|
|
126
112
|
},
|
|
127
113
|
],
|
|
128
114
|
});
|
|
129
115
|
})
|
|
130
116
|
.then(() => renderToString(app))
|
|
131
|
-
.then(() => searchOnlyWithDerivedHelpers(
|
|
117
|
+
.then(() => searchOnlyWithDerivedHelpers(instance.mainHelper))
|
|
132
118
|
.then(() => {
|
|
133
|
-
|
|
134
|
-
walkIndex(
|
|
135
|
-
|
|
119
|
+
initialResults = {};
|
|
120
|
+
walkIndex(instance.mainIndex, widget => {
|
|
121
|
+
const { _state, _rawResults } = widget.getResults();
|
|
122
|
+
|
|
123
|
+
initialResults[widget.getIndexId()] = {
|
|
124
|
+
// copy just the values of SearchParameters, not the functions
|
|
125
|
+
state: Object.keys(_state).reduce((acc, key) => {
|
|
126
|
+
// eslint-disable-next-line no-param-reassign
|
|
127
|
+
acc[key] = _state[key];
|
|
128
|
+
return acc;
|
|
129
|
+
}, {}),
|
|
130
|
+
results: _rawResults,
|
|
131
|
+
};
|
|
136
132
|
});
|
|
137
133
|
|
|
138
|
-
search.hydrate(
|
|
139
|
-
|
|
140
|
-
resultsState = Object.keys(results)
|
|
141
|
-
.map(indexId => {
|
|
142
|
-
const { _state, _rawResults } = results[indexId];
|
|
143
|
-
return [
|
|
144
|
-
indexId,
|
|
145
|
-
{
|
|
146
|
-
// copy just the values of SearchParameters, not the functions
|
|
147
|
-
_state: Object.keys(_state).reduce((acc, key) => {
|
|
148
|
-
acc[key] = _state[key];
|
|
149
|
-
return acc;
|
|
150
|
-
}, {}),
|
|
151
|
-
_rawResults,
|
|
152
|
-
},
|
|
153
|
-
];
|
|
154
|
-
})
|
|
155
|
-
.reduce(
|
|
156
|
-
(acc, [key, val]) => {
|
|
157
|
-
acc[key] = val;
|
|
158
|
-
return acc;
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
__identifier: 'stringified',
|
|
162
|
-
}
|
|
163
|
-
);
|
|
134
|
+
search.hydrate(initialResults);
|
|
164
135
|
return search.getState();
|
|
165
136
|
});
|
|
166
137
|
};
|
|
@@ -169,10 +140,10 @@ function augmentInstantSearch(
|
|
|
169
140
|
* @returns {Promise} result state to serialize and enter into .hydrate
|
|
170
141
|
*/
|
|
171
142
|
search.getState = function() {
|
|
172
|
-
if (!
|
|
143
|
+
if (!initialResults) {
|
|
173
144
|
throw new Error('You need to wait for findResultsState to finish');
|
|
174
145
|
}
|
|
175
|
-
return
|
|
146
|
+
return initialResults;
|
|
176
147
|
};
|
|
177
148
|
|
|
178
149
|
/**
|
|
@@ -184,18 +155,17 @@ function augmentInstantSearch(
|
|
|
184
155
|
* @returns {void}
|
|
185
156
|
*/
|
|
186
157
|
search.__forceRender = function(widget, parent) {
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
const results = search.__initialSearchResults[parent.getIndexId()];
|
|
158
|
+
const results = parent.getResults();
|
|
190
159
|
|
|
191
160
|
// this happens when a different InstantSearch gets rendered initially,
|
|
192
161
|
// after the hydrate finished. There's thus no initial results available.
|
|
193
|
-
if (
|
|
162
|
+
if (results === null) {
|
|
194
163
|
return;
|
|
195
164
|
}
|
|
196
165
|
|
|
197
166
|
const state = results._state;
|
|
198
167
|
|
|
168
|
+
const localHelper = parent.getHelper();
|
|
199
169
|
// helper gets created in init, but that means it doesn't get the injected
|
|
200
170
|
// parameters, because those are from the lastResults
|
|
201
171
|
localHelper.state = state;
|
|
@@ -203,11 +173,7 @@ function augmentInstantSearch(
|
|
|
203
173
|
widget.render({
|
|
204
174
|
helper: localHelper,
|
|
205
175
|
results,
|
|
206
|
-
scopedResults: parent.getScopedResults()
|
|
207
|
-
Object.assign(result, {
|
|
208
|
-
results: search.__initialSearchResults[result.indexId],
|
|
209
|
-
})
|
|
210
|
-
),
|
|
176
|
+
scopedResults: parent.getScopedResults(),
|
|
211
177
|
parent,
|
|
212
178
|
state,
|
|
213
179
|
templatesConfig: {},
|
|
@@ -232,55 +198,18 @@ function augmentInstantSearch(
|
|
|
232
198
|
return;
|
|
233
199
|
}
|
|
234
200
|
|
|
235
|
-
|
|
236
|
-
results.__identifier === 'stringified'
|
|
237
|
-
? Object.keys(results).reduce((acc, indexId) => {
|
|
238
|
-
if (indexId === '__identifier') {
|
|
239
|
-
return acc;
|
|
240
|
-
}
|
|
241
|
-
acc[indexId] = new SearchResults(
|
|
242
|
-
new SearchParameters(results[indexId]._state),
|
|
243
|
-
results[indexId]._rawResults
|
|
244
|
-
);
|
|
245
|
-
return acc;
|
|
246
|
-
}, {})
|
|
247
|
-
: results;
|
|
248
|
-
|
|
249
|
-
search.__initialSearchResults = initialResults;
|
|
201
|
+
search._initialResults = results;
|
|
250
202
|
|
|
251
|
-
search.
|
|
252
|
-
search.
|
|
253
|
-
|
|
254
|
-
search.mainIndex.init({
|
|
255
|
-
instantSearchInstance: search,
|
|
256
|
-
parent: null,
|
|
257
|
-
uiState: search._initialUiState,
|
|
258
|
-
});
|
|
203
|
+
search.start();
|
|
204
|
+
search.started = false;
|
|
259
205
|
};
|
|
260
|
-
|
|
261
|
-
/* eslint-enable no-param-reassign */
|
|
262
206
|
return search;
|
|
263
207
|
}
|
|
264
208
|
|
|
265
209
|
export function createServerRootMixin(instantSearchOptions = {}) {
|
|
266
|
-
const {
|
|
267
|
-
searchClient,
|
|
268
|
-
indexName,
|
|
269
|
-
$cloneComponent = defaultCloneComponent,
|
|
270
|
-
} = instantSearchOptions;
|
|
271
|
-
|
|
272
|
-
if (!searchClient || !indexName) {
|
|
273
|
-
throw new Error(
|
|
274
|
-
'createServerRootMixin requires `searchClient` and `indexName` in the first argument'
|
|
275
|
-
);
|
|
276
|
-
}
|
|
210
|
+
const { $cloneComponent = defaultCloneComponent } = instantSearchOptions;
|
|
277
211
|
|
|
278
|
-
const search = augmentInstantSearch(
|
|
279
|
-
instantSearchOptions,
|
|
280
|
-
searchClient,
|
|
281
|
-
indexName,
|
|
282
|
-
$cloneComponent
|
|
283
|
-
);
|
|
212
|
+
const search = augmentInstantSearch(instantSearchOptions, $cloneComponent);
|
|
284
213
|
|
|
285
214
|
// put this in the user's root Vue instance
|
|
286
215
|
// we can then reuse that InstantSearch instance seamlessly from `ais-instant-search-ssr`
|
|
@@ -292,7 +221,7 @@ export function createServerRootMixin(instantSearchOptions = {}) {
|
|
|
292
221
|
},
|
|
293
222
|
data() {
|
|
294
223
|
return {
|
|
295
|
-
// this is in data, so that the real &
|
|
224
|
+
// this is in data, so that the real & cloned render do not share
|
|
296
225
|
// the same instantsearch instance.
|
|
297
226
|
instantsearch: search,
|
|
298
227
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const createSerializedState = () => ({
|
|
2
|
-
|
|
2
|
+
results: [
|
|
3
3
|
{
|
|
4
4
|
hits: [
|
|
5
5
|
{
|
|
@@ -50,7 +50,7 @@ export const createSerializedState = () => ({
|
|
|
50
50
|
index: 'movies',
|
|
51
51
|
},
|
|
52
52
|
],
|
|
53
|
-
|
|
53
|
+
state: {
|
|
54
54
|
index: 'movies',
|
|
55
55
|
query: 'hi',
|
|
56
56
|
facets: [],
|
package/src/widgets.js
CHANGED
|
@@ -44,3 +44,6 @@ export {
|
|
|
44
44
|
export { default as AisVoiceSearch } from './components/VoiceSearch.vue';
|
|
45
45
|
export { default as AisRelevantSort } from './components/RelevantSort.vue';
|
|
46
46
|
export { default as AisDynamicWidgets } from './components/DynamicWidgets';
|
|
47
|
+
export {
|
|
48
|
+
default as AisExperimentalDynamicWidgets,
|
|
49
|
+
} from './components/ExperimentalDynamicWidgets';
|