instantsearch.js 4.31.0 → 4.33.1

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/cjs/connectors/powered-by/connectPoweredBy.js +13 -4
  3. package/cjs/lib/InstantSearch.js +4 -2
  4. package/cjs/lib/infiniteHitsCache/sessionStorage.js +16 -12
  5. package/cjs/lib/insights/client.js +6 -1
  6. package/cjs/lib/routers/history.js +89 -42
  7. package/cjs/lib/utils/detect-insights-client.js +10 -1
  8. package/cjs/lib/utils/getWidgetAttribute.js +18 -8
  9. package/cjs/lib/utils/index.js +10 -1
  10. package/cjs/lib/utils/safelyRunOnBrowser.js +30 -0
  11. package/cjs/lib/version.js +1 -1
  12. package/cjs/lib/voiceSearchHelper/index.js +5 -0
  13. package/cjs/middlewares/createMetadataMiddleware.js +13 -5
  14. package/cjs/widgets/index/index.js +1 -1
  15. package/dist/instantsearch.development.d.ts +32 -26
  16. package/dist/instantsearch.development.js +213 -84
  17. package/dist/instantsearch.development.js.map +1 -1
  18. package/dist/instantsearch.development.min.d.ts +32 -26
  19. package/dist/instantsearch.production.d.ts +32 -26
  20. package/dist/instantsearch.production.min.d.ts +32 -26
  21. package/dist/instantsearch.production.min.js +2 -2
  22. package/dist/instantsearch.production.min.js.map +1 -1
  23. package/es/connectors/powered-by/connectPoweredBy.js +14 -5
  24. package/es/lib/InstantSearch.js +4 -2
  25. package/es/lib/infiniteHitsCache/sessionStorage.js +17 -14
  26. package/es/lib/insights/client.js +6 -1
  27. package/es/lib/insights/listener.d.ts +2 -2
  28. package/es/lib/routers/history.d.ts +13 -2
  29. package/es/lib/routers/history.js +88 -42
  30. package/es/lib/utils/detect-insights-client.js +9 -1
  31. package/es/lib/utils/getWidgetAttribute.js +19 -9
  32. package/es/lib/utils/index.d.ts +1 -0
  33. package/es/lib/utils/index.js +2 -1
  34. package/es/lib/utils/safelyRunOnBrowser.d.ts +14 -0
  35. package/es/lib/utils/safelyRunOnBrowser.js +23 -0
  36. package/es/lib/version.d.ts +1 -1
  37. package/es/lib/version.js +1 -1
  38. package/es/lib/voiceSearchHelper/index.js +5 -0
  39. package/es/middlewares/createMetadataMiddleware.js +13 -5
  40. package/es/types/connector.d.ts +2 -2
  41. package/es/types/insights.d.ts +12 -15
  42. package/es/types/widget-factory.d.ts +2 -2
  43. package/es/types/widget.d.ts +2 -2
  44. package/es/widgets/index/index.js +1 -1
  45. package/package.json +5 -5
@@ -4,7 +4,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
4
4
 
5
5
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
6
 
7
- import { checkRendering, createDocumentationMessageGenerator, noop } from '../../lib/utils';
7
+ import { safelyRunOnBrowser, checkRendering, createDocumentationMessageGenerator, noop } from '../../lib/utils';
8
8
  var withUsage = createDocumentationMessageGenerator({
9
9
  name: 'powered-by',
10
10
  connector: true
@@ -17,11 +17,20 @@ var withUsage = createDocumentationMessageGenerator({
17
17
  var connectPoweredBy = function connectPoweredBy(renderFn) {
18
18
  var unmountFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
19
19
  checkRendering(renderFn, withUsage());
20
- var defaultUrl = 'https://www.algolia.com/?' + 'utm_source=instantsearch.js&' + 'utm_medium=website&' + "utm_content=".concat(typeof window !== 'undefined' && window.location ? window.location.hostname : '', "&") + 'utm_campaign=poweredby';
20
+ var defaultUrl = 'https://www.algolia.com/?' + 'utm_source=instantsearch.js&' + 'utm_medium=website&' + "utm_content=".concat(safelyRunOnBrowser(function (_ref) {
21
+ var _window$location;
22
+
23
+ var window = _ref.window;
24
+ return ((_window$location = window.location) === null || _window$location === void 0 ? void 0 : _window$location.hostname) || '';
25
+ }, {
26
+ fallback: function fallback() {
27
+ return '';
28
+ }
29
+ }), "&") + 'utm_campaign=poweredby';
21
30
  return function (widgetParams) {
22
- var _ref = widgetParams || {},
23
- _ref$url = _ref.url,
24
- url = _ref$url === void 0 ? defaultUrl : _ref$url;
31
+ var _ref2 = widgetParams || {},
32
+ _ref2$url = _ref2.url,
33
+ url = _ref2$url === void 0 ? defaultUrl : _ref2$url;
25
34
 
26
35
  return {
27
36
  $$type: 'ais.poweredBy',
@@ -501,15 +501,17 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
501
501
  var nextUiState = typeof uiState === 'function' ? uiState(this.mainIndex.getWidgetUiState({})) : uiState;
502
502
 
503
503
  var setIndexHelperState = function setIndexHelperState(indexWidget) {
504
+ var nextIndexUiState = nextUiState[indexWidget.getIndexId()] || {};
505
+
504
506
  if (process.env.NODE_ENV === 'development') {
505
507
  checkIndexUiState({
506
508
  index: indexWidget,
507
- indexUiState: nextUiState[indexWidget.getIndexId()]
509
+ indexUiState: nextIndexUiState
508
510
  });
509
511
  }
510
512
 
511
513
  indexWidget.getHelper().setState(indexWidget.getWidgetSearchParameters(indexWidget.getHelper().state, {
512
- uiState: nextUiState[indexWidget.getIndexId()]
514
+ uiState: nextIndexUiState
513
515
  }));
514
516
  indexWidget.getWidgets().filter(isIndexWidget).forEach(setIndexHelperState);
515
517
  };
@@ -2,7 +2,7 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return
2
2
 
3
3
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
4
4
 
5
- import { isEqual } from '../utils';
5
+ import { isEqual, safelyRunOnBrowser } from '../utils';
6
6
 
7
7
  function getStateWithoutPage(state) {
8
8
  var _ref = state || {},
@@ -13,28 +13,27 @@ function getStateWithoutPage(state) {
13
13
  }
14
14
 
15
15
  var KEY = 'ais.infiniteHits';
16
-
17
- function hasSessionStorage() {
18
- return typeof window !== 'undefined' && typeof window.sessionStorage !== 'undefined';
19
- }
20
-
21
16
  export default function createInfiniteHitsSessionStorageCache() {
22
17
  return {
23
18
  read: function read(_ref2) {
24
19
  var state = _ref2.state;
20
+ var sessionStorage = safelyRunOnBrowser(function (_ref3) {
21
+ var window = _ref3.window;
22
+ return window.sessionStorage;
23
+ });
25
24
 
26
- if (!hasSessionStorage()) {
25
+ if (!sessionStorage) {
27
26
  return null;
28
27
  }
29
28
 
30
29
  try {
31
30
  var cache = JSON.parse( // @ts-expect-error JSON.parse() requires a string, but it actually accepts null, too.
32
- window.sessionStorage.getItem(KEY));
31
+ sessionStorage.getItem(KEY));
33
32
  return cache && isEqual(cache.state, getStateWithoutPage(state)) ? cache.hits : null;
34
33
  } catch (error) {
35
34
  if (error instanceof SyntaxError) {
36
35
  try {
37
- window.sessionStorage.removeItem(KEY);
36
+ sessionStorage.removeItem(KEY);
38
37
  } catch (err) {// do nothing
39
38
  }
40
39
  }
@@ -42,16 +41,20 @@ export default function createInfiniteHitsSessionStorageCache() {
42
41
  return null;
43
42
  }
44
43
  },
45
- write: function write(_ref3) {
46
- var state = _ref3.state,
47
- hits = _ref3.hits;
44
+ write: function write(_ref4) {
45
+ var state = _ref4.state,
46
+ hits = _ref4.hits;
47
+ var sessionStorage = safelyRunOnBrowser(function (_ref5) {
48
+ var window = _ref5.window;
49
+ return window.sessionStorage;
50
+ });
48
51
 
49
- if (!hasSessionStorage()) {
52
+ if (!sessionStorage) {
50
53
  return;
51
54
  }
52
55
 
53
56
  try {
54
- window.sessionStorage.setItem(KEY, JSON.stringify({
57
+ sessionStorage.setItem(KEY, JSON.stringify({
55
58
  state: getStateWithoutPage(state),
56
59
  hits: hits
57
60
  }));
@@ -78,7 +78,12 @@ export var inferPayload = function inferPayload(_ref) {
78
78
  };
79
79
 
80
80
  var wrapInsightsClient = function wrapInsightsClient(aa, results, hits) {
81
- return function (method, payload) {
81
+ return function (method) {
82
+ for (var _len = arguments.length, payloads = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
83
+ payloads[_key - 1] = arguments[_key];
84
+ }
85
+
86
+ var payload = payloads[0];
82
87
  process.env.NODE_ENV === 'development' ? warning(false, "`insights` function has been deprecated. It is still supported in 4.x releases, but not further. It is replaced by the `insights` middleware.\n\nFor more information, visit https://www.algolia.com/doc/guides/getting-insights-and-analytics/search-analytics/click-through-and-conversions/how-to/send-click-and-conversion-events-with-instantsearch/js/") : void 0;
83
88
 
84
89
  if (!aa) {
@@ -1,10 +1,10 @@
1
1
  /** @jsx h */
2
2
  import { h } from 'preact';
3
- import type { InsightsClientWrapper } from '../../types';
3
+ import type { InsightsClient } from '../../types';
4
4
  import type { InsightsEvent } from '../../middlewares/createInsightsMiddleware';
5
5
  declare type WithInsightsListenerProps = {
6
6
  [key: string]: unknown;
7
- insights: InsightsClientWrapper;
7
+ insights: InsightsClient;
8
8
  sendEvent?: (event: InsightsEvent) => void;
9
9
  };
10
10
  declare const insightsListener: (BaseComponent: any) => (props: WithInsightsListenerProps) => h.JSX.Element;
@@ -14,6 +14,7 @@ declare type BrowserHistoryArgs<TRouteState> = {
14
14
  writeDelay: number;
15
15
  createURL: CreateURL<TRouteState>;
16
16
  parseURL: ParseURL<TRouteState>;
17
+ getLocation(): Location;
17
18
  };
18
19
  declare class BrowserHistory<TRouteState> implements Router<TRouteState> {
19
20
  /**
@@ -38,13 +39,23 @@ declare class BrowserHistory<TRouteState> implements Router<TRouteState> {
38
39
  * It should be symmetrical to `createURL`.
39
40
  */
40
41
  private readonly parseURL;
42
+ /**
43
+ * Returns the location to store in the history.
44
+ * @default () => window.location
45
+ */
46
+ private readonly getLocation;
41
47
  private writeTimer?;
42
48
  private _onPopState;
49
+ /**
50
+ * Indicates if history.pushState should be executed.
51
+ * It needs to avoid pushing state to history in case of back/forward in browser
52
+ */
53
+ private shouldPushState;
43
54
  /**
44
55
  * Initializes a new storage provider that syncs the search state to the URL
45
56
  * using web APIs (`window.location.pushState` and `onpopstate` event).
46
57
  */
47
- constructor({ windowTitle, writeDelay, createURL, parseURL, }: BrowserHistoryArgs<TRouteState>);
58
+ constructor({ windowTitle, writeDelay, createURL, parseURL, getLocation, }: BrowserHistoryArgs<TRouteState>);
48
59
  /**
49
60
  * Reads the URL and returns a syncable UI search state.
50
61
  */
@@ -71,5 +82,5 @@ declare class BrowserHistory<TRouteState> implements Router<TRouteState> {
71
82
  */
72
83
  dispose(): void;
73
84
  }
74
- export default function historyRouter<TRouteState = UiState>({ createURL, parseURL, writeDelay, windowTitle, }?: Partial<BrowserHistoryArgs<TRouteState>>): BrowserHistory<TRouteState>;
85
+ export default function historyRouter<TRouteState = UiState>({ createURL, parseURL, writeDelay, windowTitle, getLocation, }?: Partial<BrowserHistoryArgs<TRouteState>>): BrowserHistory<TRouteState>;
75
86
  export {};
@@ -7,9 +7,12 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
7
7
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
8
 
9
9
  import qs from 'qs';
10
+ import { safelyRunOnBrowser } from '../utils';
10
11
 
11
12
  var setWindowTitle = function setWindowTitle(title) {
12
13
  if (title) {
14
+ // This function is only executed on browsers so we can disable this check.
15
+ // eslint-disable-next-line no-restricted-globals
13
16
  window.document.title = title;
14
17
  }
15
18
  };
@@ -20,11 +23,14 @@ var BrowserHistory = /*#__PURE__*/function () {
20
23
  * using web APIs (`window.location.pushState` and `onpopstate` event).
21
24
  */
22
25
  function BrowserHistory(_ref) {
26
+ var _this = this;
27
+
23
28
  var windowTitle = _ref.windowTitle,
24
29
  _ref$writeDelay = _ref.writeDelay,
25
30
  writeDelay = _ref$writeDelay === void 0 ? 400 : _ref$writeDelay,
26
31
  createURL = _ref.createURL,
27
- parseURL = _ref.parseURL;
32
+ parseURL = _ref.parseURL,
33
+ getLocation = _ref.getLocation;
28
34
 
29
35
  _classCallCheck(this, BrowserHistory);
30
36
 
@@ -36,15 +42,23 @@ var BrowserHistory = /*#__PURE__*/function () {
36
42
 
37
43
  _defineProperty(this, "parseURL", void 0);
38
44
 
45
+ _defineProperty(this, "getLocation", void 0);
46
+
39
47
  _defineProperty(this, "writeTimer", void 0);
40
48
 
49
+ _defineProperty(this, "shouldPushState", true);
50
+
41
51
  this.windowTitle = windowTitle;
42
52
  this.writeTimer = undefined;
43
53
  this.writeDelay = writeDelay;
44
54
  this._createURL = createURL;
45
55
  this.parseURL = parseURL;
46
- var title = this.windowTitle && this.windowTitle(this.read());
47
- setWindowTitle(title);
56
+ this.getLocation = getLocation;
57
+ safelyRunOnBrowser(function () {
58
+ var title = _this.windowTitle && _this.windowTitle(_this.read());
59
+
60
+ setWindowTitle(title);
61
+ });
48
62
  }
49
63
  /**
50
64
  * Reads the URL and returns a syncable UI search state.
@@ -56,7 +70,7 @@ var BrowserHistory = /*#__PURE__*/function () {
56
70
  value: function read() {
57
71
  return this.parseURL({
58
72
  qsModule: qs,
59
- location: window.location
73
+ location: this.getLocation()
60
74
  });
61
75
  }
62
76
  /**
@@ -66,20 +80,30 @@ var BrowserHistory = /*#__PURE__*/function () {
66
80
  }, {
67
81
  key: "write",
68
82
  value: function write(routeState) {
69
- var _this = this;
83
+ var _this2 = this;
70
84
 
71
- var url = this.createURL(routeState);
72
- var title = this.windowTitle && this.windowTitle(routeState);
85
+ safelyRunOnBrowser(function (_ref2) {
86
+ var window = _ref2.window;
73
87
 
74
- if (this.writeTimer) {
75
- window.clearTimeout(this.writeTimer);
76
- }
88
+ var url = _this2.createURL(routeState);
89
+
90
+ var title = _this2.windowTitle && _this2.windowTitle(routeState);
91
+
92
+ if (_this2.writeTimer) {
93
+ clearTimeout(_this2.writeTimer);
94
+ }
95
+
96
+ _this2.writeTimer = setTimeout(function () {
97
+ setWindowTitle(title);
98
+
99
+ if (_this2.shouldPushState) {
100
+ window.history.pushState(routeState, title || '', url);
101
+ }
77
102
 
78
- this.writeTimer = window.setTimeout(function () {
79
- setWindowTitle(title);
80
- window.history.pushState(routeState, title || '', url);
81
- _this.writeTimer = undefined;
82
- }, this.writeDelay);
103
+ _this2.shouldPushState = true;
104
+ _this2.writeTimer = undefined;
105
+ }, _this2.writeDelay);
106
+ });
83
107
  }
84
108
  /**
85
109
  * Sets a callback on the `onpopstate` event of the history API of the current page.
@@ -89,26 +113,30 @@ var BrowserHistory = /*#__PURE__*/function () {
89
113
  }, {
90
114
  key: "onUpdate",
91
115
  value: function onUpdate(callback) {
92
- var _this2 = this;
116
+ var _this3 = this;
93
117
 
94
118
  this._onPopState = function (event) {
95
- if (_this2.writeTimer) {
96
- window.clearTimeout(_this2.writeTimer);
97
- _this2.writeTimer = undefined;
119
+ if (_this3.writeTimer) {
120
+ clearTimeout(_this3.writeTimer);
121
+ _this3.writeTimer = undefined;
98
122
  }
99
123
 
124
+ _this3.shouldPushState = false;
100
125
  var routeState = event.state; // At initial load, the state is read from the URL without update.
101
126
  // Therefore the state object is not available.
102
127
  // In this case, we fallback and read the URL.
103
128
 
104
129
  if (!routeState) {
105
- callback(_this2.read());
130
+ callback(_this3.read());
106
131
  } else {
107
132
  callback(routeState);
108
133
  }
109
134
  };
110
135
 
111
- window.addEventListener('popstate', this._onPopState);
136
+ safelyRunOnBrowser(function (_ref3) {
137
+ var window = _ref3.window;
138
+ window.addEventListener('popstate', _this3._onPopState);
139
+ });
112
140
  }
113
141
  /**
114
142
  * Creates a complete URL from a given syncable UI state.
@@ -124,7 +152,7 @@ var BrowserHistory = /*#__PURE__*/function () {
124
152
  return this._createURL({
125
153
  qsModule: qs,
126
154
  routeState: routeState,
127
- location: window.location
155
+ location: this.getLocation()
128
156
  });
129
157
  }
130
158
  /**
@@ -134,12 +162,18 @@ var BrowserHistory = /*#__PURE__*/function () {
134
162
  }, {
135
163
  key: "dispose",
136
164
  value: function dispose() {
137
- if (this._onPopState) {
138
- window.removeEventListener('popstate', this._onPopState);
139
- }
165
+ var _this4 = this;
166
+
167
+ safelyRunOnBrowser(function (_ref4) {
168
+ var window = _ref4.window;
169
+
170
+ if (_this4._onPopState) {
171
+ window.removeEventListener('popstate', _this4._onPopState);
172
+ }
173
+ });
140
174
 
141
175
  if (this.writeTimer) {
142
- window.clearTimeout(this.writeTimer);
176
+ clearTimeout(this.writeTimer);
143
177
  }
144
178
 
145
179
  this.write({});
@@ -150,12 +184,12 @@ var BrowserHistory = /*#__PURE__*/function () {
150
184
  }();
151
185
 
152
186
  export default function historyRouter() {
153
- var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
154
- _ref2$createURL = _ref2.createURL,
155
- createURL = _ref2$createURL === void 0 ? function (_ref3) {
156
- var qsModule = _ref3.qsModule,
157
- routeState = _ref3.routeState,
158
- location = _ref3.location;
187
+ var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
188
+ _ref5$createURL = _ref5.createURL,
189
+ createURL = _ref5$createURL === void 0 ? function (_ref6) {
190
+ var qsModule = _ref6.qsModule,
191
+ routeState = _ref6.routeState,
192
+ location = _ref6.location;
159
193
  var protocol = location.protocol,
160
194
  hostname = location.hostname,
161
195
  _location$port = location.port,
@@ -171,11 +205,11 @@ export default function historyRouter() {
171
205
  }
172
206
 
173
207
  return "".concat(protocol, "//").concat(hostname).concat(portWithPrefix).concat(pathname, "?").concat(queryString).concat(hash);
174
- } : _ref2$createURL,
175
- _ref2$parseURL = _ref2.parseURL,
176
- parseURL = _ref2$parseURL === void 0 ? function (_ref4) {
177
- var qsModule = _ref4.qsModule,
178
- location = _ref4.location;
208
+ } : _ref5$createURL,
209
+ _ref5$parseURL = _ref5.parseURL,
210
+ parseURL = _ref5$parseURL === void 0 ? function (_ref7) {
211
+ var qsModule = _ref7.qsModule,
212
+ location = _ref7.location;
179
213
  // `qs` by default converts arrays with more than 20 items to an object.
180
214
  // We want to avoid this because the data structure manipulated can therefore vary.
181
215
  // Setting the limit to `100` seems a good number because the engine's default is 100
@@ -189,15 +223,27 @@ export default function historyRouter() {
189
223
  return qsModule.parse(location.search.slice(1), {
190
224
  arrayLimit: 99
191
225
  });
192
- } : _ref2$parseURL,
193
- _ref2$writeDelay = _ref2.writeDelay,
194
- writeDelay = _ref2$writeDelay === void 0 ? 400 : _ref2$writeDelay,
195
- windowTitle = _ref2.windowTitle;
226
+ } : _ref5$parseURL,
227
+ _ref5$writeDelay = _ref5.writeDelay,
228
+ writeDelay = _ref5$writeDelay === void 0 ? 400 : _ref5$writeDelay,
229
+ windowTitle = _ref5.windowTitle,
230
+ _ref5$getLocation = _ref5.getLocation,
231
+ getLocation = _ref5$getLocation === void 0 ? function () {
232
+ return safelyRunOnBrowser(function (_ref8) {
233
+ var window = _ref8.window;
234
+ return window.location;
235
+ }, {
236
+ fallback: function fallback() {
237
+ throw new Error('You need to provide `getLocation` to the `history` router in environments where `window` does not exist.');
238
+ }
239
+ });
240
+ } : _ref5$getLocation;
196
241
 
197
242
  return new BrowserHistory({
198
243
  createURL: createURL,
199
244
  parseURL: parseURL,
200
245
  writeDelay: writeDelay,
201
- windowTitle: windowTitle
246
+ windowTitle: windowTitle,
247
+ getLocation: getLocation
202
248
  });
203
249
  }
@@ -1,3 +1,11 @@
1
+ import { safelyRunOnBrowser } from './safelyRunOnBrowser';
1
2
  export default function hasDetectedInsightsClient() {
2
- return typeof window !== 'undefined' && Boolean(window.AlgoliaAnalyticsObject);
3
+ return safelyRunOnBrowser(function (_ref) {
4
+ var window = _ref.window;
5
+ return Boolean(window.AlgoliaAnalyticsObject);
6
+ }, {
7
+ fallback: function fallback() {
8
+ return false;
9
+ }
10
+ });
3
11
  }
@@ -1,13 +1,23 @@
1
1
  export function getWidgetAttribute(widget, initOptions) {
2
- try {
3
- // assume the type to be the correct one, but throw a nice error if it isn't the case
4
- var _getWidgetRenderState = widget.getWidgetRenderState(initOptions),
5
- widgetParams = _getWidgetRenderState.widgetParams;
6
-
7
- var attribute = 'attribute' in widgetParams ? widgetParams.attribute : widgetParams.attributes[0];
8
- if (typeof attribute !== 'string') throw new Error();
9
- return attribute;
10
- } catch (e) {
2
+ var _widget$getWidgetRend;
3
+
4
+ var renderState = (_widget$getWidgetRend = widget.getWidgetRenderState) === null || _widget$getWidgetRend === void 0 ? void 0 : _widget$getWidgetRend.call(widget, initOptions);
5
+ var attribute = null;
6
+
7
+ if (renderState && renderState.widgetParams) {
8
+ // casting as widgetParams is checked just before
9
+ var widgetParams = renderState.widgetParams;
10
+
11
+ if (widgetParams.attribute) {
12
+ attribute = widgetParams.attribute;
13
+ } else if (Array.isArray(widgetParams.attributes)) {
14
+ attribute = widgetParams.attributes[0];
15
+ }
16
+ }
17
+
18
+ if (typeof attribute !== 'string') {
11
19
  throw new Error("Could not find the attribute of the widget:\n\n".concat(JSON.stringify(widget), "\n\nPlease check whether the widget's getWidgetRenderState returns widgetParams.attribute correctly."));
12
20
  }
21
+
22
+ return attribute;
13
23
  }
@@ -45,3 +45,4 @@ export { createConcurrentSafePromise } from './createConcurrentSafePromise';
45
45
  export { debounce } from './debounce';
46
46
  export { serializePayload, deserializePayload } from './serializer';
47
47
  export { getWidgetAttribute } from './getWidgetAttribute';
48
+ export { safelyRunOnBrowser } from './safelyRunOnBrowser';
@@ -44,4 +44,5 @@ export { convertNumericRefinementsToFilters } from './convertNumericRefinementsT
44
44
  export { createConcurrentSafePromise } from './createConcurrentSafePromise';
45
45
  export { debounce } from './debounce';
46
46
  export { serializePayload, deserializePayload } from './serializer';
47
- export { getWidgetAttribute } from './getWidgetAttribute';
47
+ export { getWidgetAttribute } from './getWidgetAttribute';
48
+ export { safelyRunOnBrowser } from './safelyRunOnBrowser';
@@ -0,0 +1,14 @@
1
+ declare type BrowserCallback<TReturn> = (params: {
2
+ window: typeof window;
3
+ }) => TReturn;
4
+ declare type SafelyRunOnBrowserOptions<TReturn> = {
5
+ /**
6
+ * Fallback to run on server environments.
7
+ */
8
+ fallback: () => TReturn;
9
+ };
10
+ /**
11
+ * Runs code on browser enviromnents safely.
12
+ */
13
+ export declare function safelyRunOnBrowser<TReturn>(callback: BrowserCallback<TReturn>, { fallback }?: SafelyRunOnBrowserOptions<TReturn>): TReturn;
14
+ export {};
@@ -0,0 +1,23 @@
1
+ // eslint-disable-next-line no-restricted-globals
2
+
3
+ /**
4
+ * Runs code on browser enviromnents safely.
5
+ */
6
+ export function safelyRunOnBrowser(callback) {
7
+ var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
8
+ fallback: function fallback() {
9
+ return undefined;
10
+ }
11
+ },
12
+ fallback = _ref.fallback;
13
+
14
+ // eslint-disable-next-line no-restricted-globals
15
+ if (typeof window === 'undefined') {
16
+ return fallback();
17
+ } // eslint-disable-next-line no-restricted-globals
18
+
19
+
20
+ return callback({
21
+ window: window
22
+ });
23
+ }
@@ -1,2 +1,2 @@
1
- declare const _default: "4.31.0";
1
+ declare const _default: "4.33.1";
2
2
  export default _default;
package/es/lib/version.js CHANGED
@@ -1 +1 @@
1
- export default '4.31.0';
1
+ export default '4.33.1';
@@ -4,6 +4,11 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
4
4
 
5
5
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
6
 
7
+ // `SpeechRecognition` is an API used on the browser so we can safely disable
8
+ // the `window` check.
9
+
10
+ /* eslint-disable no-restricted-globals */
11
+
7
12
  /* global SpeechRecognition SpeechRecognitionEvent */
8
13
  var createVoiceSearchHelper = function createVoiceSearchHelper(_ref) {
9
14
  var searchAsYouSpeak = _ref.searchAsYouSpeak,
@@ -1,4 +1,4 @@
1
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
1
+ import { safelyRunOnBrowser } from '../lib/utils';
2
2
 
3
3
  function extractPayload(widgets, instantSearchInstance, payload) {
4
4
  var parent = instantSearchInstance.mainIndex;
@@ -22,7 +22,8 @@ function extractPayload(widgets, instantSearchInstance, payload) {
22
22
  if (widget.getWidgetRenderState) {
23
23
  var renderState = widget.getWidgetRenderState(initOptions);
24
24
 
25
- if (renderState && _typeof(renderState.widgetParams) === 'object') {
25
+ if (renderState && renderState.widgetParams) {
26
+ // casting, as we just earlier checked widgetParams exists, and thus an object
26
27
  widgetParams = renderState.widgetParams;
27
28
  }
28
29
  } // since we destructure in all widgets, the parameters with defaults are set to "undefined"
@@ -44,7 +45,14 @@ function extractPayload(widgets, instantSearchInstance, payload) {
44
45
  }
45
46
 
46
47
  export function isMetadataEnabled() {
47
- return typeof window !== 'undefined' && window.navigator.userAgent.indexOf('Algolia Crawler') > -1;
48
+ return safelyRunOnBrowser(function (_ref) {
49
+ var window = _ref.window;
50
+ return window.navigator.userAgent.indexOf('Algolia Crawler') > -1;
51
+ }, {
52
+ fallback: function fallback() {
53
+ return false;
54
+ }
55
+ });
48
56
  }
49
57
  /**
50
58
  * Exposes the metadata of mounted widgets in a custom
@@ -55,8 +63,8 @@ export function isMetadataEnabled() {
55
63
  */
56
64
 
57
65
  export function createMetadataMiddleware() {
58
- return function (_ref) {
59
- var instantSearchInstance = _ref.instantSearchInstance;
66
+ return function (_ref2) {
67
+ var instantSearchInstance = _ref2.instantSearchInstance;
60
68
  var payload = {
61
69
  widgets: []
62
70
  };
@@ -2,7 +2,7 @@ import type { SearchResults } from 'algoliasearch-helper';
2
2
  import type { InstantSearch } from './instantsearch';
3
3
  import type { InsightsClient } from './insights';
4
4
  import type { Hits } from './results';
5
- import type { Widget, WidgetDescription } from './widget';
5
+ import type { UnknownWidgetParams, Widget, WidgetDescription } from './widget';
6
6
  /**
7
7
  * The base renderer options. All render functions receive
8
8
  * the options below plus the specific options per connector.
@@ -51,7 +51,7 @@ export declare type Unmounter = () => void;
51
51
  * The connector handles the business logic and exposes
52
52
  * a simplified API to the rendering function.
53
53
  */
54
- export declare type Connector<TWidgetDescription extends WidgetDescription, TConnectorParams> = <TWidgetParams>(
54
+ export declare type Connector<TWidgetDescription extends WidgetDescription, TConnectorParams extends UnknownWidgetParams> = <TWidgetParams extends UnknownWidgetParams>(
55
55
  /**
56
56
  * The render function.
57
57
  */