atriusmaps-node-sdk 3.3.196 → 3.3.226

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 (109) hide show
  1. package/dist/cjs/_virtual/_empty_module_placeholder.js +2 -2
  2. package/dist/cjs/deploy/prepareSDKConfig.js +152 -2
  3. package/dist/cjs/nodesdk/nodeEntry.js +109 -0
  4. package/dist/cjs/package.json.js +190 -14
  5. package/dist/cjs/plugins/clientAPI/src/clientAPI.js +11 -2
  6. package/dist/cjs/plugins/dynamicPois/src/dynamicPois.js +218 -21
  7. package/dist/cjs/plugins/poiDataManager/src/poiDataManager.js +292 -21
  8. package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +99 -20
  9. package/dist/cjs/plugins/sdkServer/src/sdkServer.js +219 -2
  10. package/dist/cjs/plugins/sdkServer/src/util.js +16 -3
  11. package/dist/cjs/plugins/searchService/src/poiSearch.js +57 -19
  12. package/dist/cjs/plugins/searchService/src/searchService.js +246 -21
  13. package/dist/cjs/plugins/searchService/src/searchTypeahead.js +60 -3
  14. package/dist/cjs/plugins/searchService/src/utils.js +23 -4
  15. package/dist/cjs/plugins/venueDataLoader/src/venueDataLoader.js +472 -21
  16. package/dist/cjs/plugins/venueDataLoader/src/venueLoadingUtils.js +191 -23
  17. package/dist/cjs/plugins/wayfinder/src/findRoute.js +147 -19
  18. package/dist/cjs/plugins/wayfinder/src/minPriorityQueue.js +88 -2
  19. package/dist/cjs/plugins/wayfinder/src/navGraph.js +393 -5
  20. package/dist/cjs/plugins/wayfinder/src/navGraphDebug.js +110 -20
  21. package/dist/cjs/plugins/wayfinder/src/segmentBadges.js +28 -2
  22. package/dist/cjs/plugins/wayfinder/src/segmentBuilder.js +257 -19
  23. package/dist/cjs/plugins/wayfinder/src/segmentCategories.js +29 -2
  24. package/dist/cjs/plugins/wayfinder/src/stepBuilder.js +238 -3
  25. package/dist/cjs/plugins/wayfinder/src/wayfinder.js +597 -22
  26. package/dist/cjs/src/app.js +191 -25
  27. package/dist/cjs/src/configs/postproc-mol-url-parms.js +58 -2
  28. package/dist/cjs/src/configs/postproc-stateTracking.js +53 -19
  29. package/dist/cjs/src/controller.js +43 -4
  30. package/dist/cjs/src/debugTools.js +128 -23
  31. package/dist/cjs/src/env.js +17 -2
  32. package/dist/cjs/src/extModules/bustle.js +128 -4
  33. package/dist/cjs/src/extModules/flexapi/src/help.js +23 -4
  34. package/dist/cjs/src/extModules/flexapi/src/index.js +65 -4
  35. package/dist/cjs/src/extModules/flexapi/src/validate.js +133 -5
  36. package/dist/cjs/src/extModules/geohasher.js +90 -3
  37. package/dist/cjs/src/extModules/log.js +69 -2
  38. package/dist/cjs/src/historyManager.js +29 -2
  39. package/dist/cjs/src/utils/bounds.js +22 -4
  40. package/dist/cjs/src/utils/buildStructureLookup.js +31 -19
  41. package/dist/cjs/src/utils/configUtils.js +71 -3
  42. package/dist/cjs/src/utils/dom.js +48 -5
  43. package/dist/cjs/src/utils/funcs.js +30 -3
  44. package/dist/cjs/src/utils/geodesy.js +35 -3
  45. package/dist/cjs/src/utils/geom.js +209 -27
  46. package/dist/cjs/src/utils/i18n.js +69 -5
  47. package/dist/cjs/src/utils/observable.js +73 -2
  48. package/dist/cjs/src/utils/rand.js +82 -3
  49. package/dist/nodesdk/nodeEntry.js +1 -0
  50. package/dist/package.json.js +1 -0
  51. package/dist/plugins/searchService/src/searchService.js +1 -0
  52. package/dist/plugins/venueDataLoader/src/venueDataLoader.js +1 -0
  53. package/dist/plugins/venueDataLoader/src/venueLoadingUtils.js +1 -0
  54. package/dist/src/app.js +1 -0
  55. package/package.json +13 -9
  56. package/.yarnrc.yml +0 -1
  57. package/config/rollup.config.cjs.js +0 -31
  58. package/dist/cjs/deploy/nodeEntry.js +0 -20
  59. package/dist/cjs/src/auth/Auth.js +0 -23
  60. package/lib/deploy/nodeEntry.js +0 -1
  61. package/lib/package.json.js +0 -1
  62. package/lib/plugins/searchService/src/searchService.js +0 -1
  63. package/lib/plugins/venueDataLoader/src/venueDataLoader.js +0 -1
  64. package/lib/plugins/venueDataLoader/src/venueLoadingUtils.js +0 -1
  65. package/lib/src/app.js +0 -1
  66. package/lib/src/configs/sdkHeadless.json +0 -28
  67. /package/{lib → dist}/_virtual/_empty_module_placeholder.js +0 -0
  68. /package/{lib → dist}/deploy/prepareSDKConfig.js +0 -0
  69. /package/{lib → dist}/plugins/clientAPI/src/clientAPI.js +0 -0
  70. /package/{lib → dist}/plugins/dynamicPois/src/dynamicPois.js +0 -0
  71. /package/{lib → dist}/plugins/poiDataManager/src/poiDataManager.js +0 -0
  72. /package/{lib → dist}/plugins/sdkServer/src/sdkHeadless.js +0 -0
  73. /package/{lib → dist}/plugins/sdkServer/src/sdkServer.js +0 -0
  74. /package/{lib → dist}/plugins/sdkServer/src/util.js +0 -0
  75. /package/{lib → dist}/plugins/searchService/src/poiSearch.js +0 -0
  76. /package/{lib → dist}/plugins/searchService/src/searchTypeahead.js +0 -0
  77. /package/{lib → dist}/plugins/searchService/src/utils.js +0 -0
  78. /package/{lib → dist}/plugins/wayfinder/src/findRoute.js +0 -0
  79. /package/{lib → dist}/plugins/wayfinder/src/minPriorityQueue.js +0 -0
  80. /package/{lib → dist}/plugins/wayfinder/src/navGraph.js +0 -0
  81. /package/{lib → dist}/plugins/wayfinder/src/navGraphDebug.js +0 -0
  82. /package/{lib → dist}/plugins/wayfinder/src/segmentBadges.js +0 -0
  83. /package/{lib → dist}/plugins/wayfinder/src/segmentBuilder.js +0 -0
  84. /package/{lib → dist}/plugins/wayfinder/src/segmentCategories.js +0 -0
  85. /package/{lib → dist}/plugins/wayfinder/src/stepBuilder.js +0 -0
  86. /package/{lib → dist}/plugins/wayfinder/src/wayfinder.js +0 -0
  87. /package/{lib → dist}/src/configs/postproc-mol-url-parms.js +0 -0
  88. /package/{lib → dist}/src/configs/postproc-stateTracking.js +0 -0
  89. /package/{lib → dist}/src/configs/sdkHeadless.json.js +0 -0
  90. /package/{lib → dist}/src/controller.js +0 -0
  91. /package/{lib → dist}/src/debugTools.js +0 -0
  92. /package/{lib → dist}/src/env.js +0 -0
  93. /package/{lib → dist}/src/extModules/bustle.js +0 -0
  94. /package/{lib → dist}/src/extModules/flexapi/src/help.js +0 -0
  95. /package/{lib → dist}/src/extModules/flexapi/src/index.js +0 -0
  96. /package/{lib → dist}/src/extModules/flexapi/src/validate.js +0 -0
  97. /package/{lib → dist}/src/extModules/geohasher.js +0 -0
  98. /package/{lib → dist}/src/extModules/log.js +0 -0
  99. /package/{lib → dist}/src/historyManager.js +0 -0
  100. /package/{lib → dist}/src/utils/bounds.js +0 -0
  101. /package/{lib → dist}/src/utils/buildStructureLookup.js +0 -0
  102. /package/{lib → dist}/src/utils/configUtils.js +0 -0
  103. /package/{lib → dist}/src/utils/dom.js +0 -0
  104. /package/{lib → dist}/src/utils/funcs.js +0 -0
  105. /package/{lib → dist}/src/utils/geodesy.js +0 -0
  106. /package/{lib → dist}/src/utils/geom.js +0 -0
  107. /package/{lib → dist}/src/utils/i18n.js +0 -0
  108. /package/{lib → dist}/src/utils/observable.js +0 -0
  109. /package/{lib → dist}/src/utils/rand.js +0 -0
@@ -2,8 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var e = require('ramda');
6
- var a = require('zousan');
5
+ var R = require('ramda');
6
+ var Zousan = require('zousan');
7
7
  var configUtils = require('../../../src/utils/configUtils.js');
8
8
  var rand = require('../../../src/utils/rand.js');
9
9
  var poiSearch = require('./poiSearch.js');
@@ -12,26 +12,251 @@ var searchTypeahead = require('./searchTypeahead.js');
12
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
13
 
14
14
  function _interopNamespace(e) {
15
- if (e && e.__esModule) return e;
16
- var n = Object.create(null);
17
- if (e) {
18
- Object.keys(e).forEach(function (k) {
19
- if (k !== 'default') {
20
- var d = Object.getOwnPropertyDescriptor(e, k);
21
- Object.defineProperty(n, k, d.get ? d : {
22
- enumerable: true,
23
- get: function () { return e[k]; }
24
- });
25
- }
26
- });
27
- }
28
- n["default"] = e;
29
- return Object.freeze(n);
15
+ if (e && e.__esModule) return e;
16
+ var n = Object.create(null);
17
+ if (e) {
18
+ Object.keys(e).forEach(function (k) {
19
+ if (k !== 'default') {
20
+ var d = Object.getOwnPropertyDescriptor(e, k);
21
+ Object.defineProperty(n, k, d.get ? d : {
22
+ enumerable: true,
23
+ get: function () { return e[k]; }
24
+ });
25
+ }
26
+ });
27
+ }
28
+ n["default"] = e;
29
+ return Object.freeze(n);
30
30
  }
31
31
 
32
- var e__namespace = /*#__PURE__*/_interopNamespace(e);
33
- var a__default = /*#__PURE__*/_interopDefaultLegacy(a);
32
+ var R__namespace = /*#__PURE__*/_interopNamespace(R);
33
+ var Zousan__default = /*#__PURE__*/_interopDefaultLegacy(Zousan);
34
34
 
35
- function o(o,i){const c={poiSearch:null,typeahead:null,indexesCreated:new a__default["default"],defaultSearchTerms:null,specialQueryTerms:{}},u=async()=>{const e=await o.bus.get("poi/getAll");c.poiSearch=poiSearch(e,o.i18n().language),c.typeahead=searchTypeahead(e,c.poiSearch.search,o.i18n().language),c.defaultSearchTerms=configUtils.getLocalized(i,"defaultSearchTerms",o.i18n().language),c.indexesCreated.resolve();};async function d(){const r=await o.bus.get("user/getPhysicalLocation"),a=await o.bus.get("poi/getByFloorId",{floorId:r.floorId}),s=Object.values(e__namespace.pickBy((e=>-1===e.category.indexOf("portal")&&"element.door"!==e.category),a)),t=await o.bus.get("wayfinder/addPathTimeMultiple",{pois:s,startLocation:r});return e__namespace.sortBy(e__namespace.prop("distance"),Object.values(t)).slice(0,50)}o.bus.on("search/queryNearby",(async()=>{const e=await d();return o.bus.send("search/showNearby",{pois:e,term:"Nearby"}),e})),o.bus.on("search/queryNearbyAsync",d),o.bus.on("search/queryCategory",(async({category:e,categoryName:r,searchTerm:a})=>{const s=await c.indexesCreated.then((()=>c.poiSearch.search({query:a||e})));return o.bus.send("search/showCategory",{pois:s,category:e,categoryName:r}),s})),o.bus.on("search/query",(({term:e})=>c.indexesCreated.then((()=>{const r=c.poiSearch.search({query:e});return o.bus.send("search/showSearchResults",{results:r,term:e}),r})))),o.bus.on("search/queryAsync",(({term:e})=>c.indexesCreated.then((()=>c.poiSearch.search({query:e}))))),o.bus.on("search/queryWithSpecial",(({term:e})=>{if(c.specialQueryTerms[e]){const{event:r,params:a}=c.specialQueryTerms[e];return o.bus.send(r,a)}return o.bus.get("search/query",{term:e})})),o.bus.on("search/getDefaultSearchTerms",(async({limit:e=5}={})=>{const r=c.defaultSearchTerms,a=r&&r.length?r:await async function(e){const r=(await o.bus.send("poi/getAllCategories"))[0],a=Array.from(new Set(r));return function(e){for(let r=e.length-1;r>0;r--){const a=Math.floor(Math.random()*(r+1));[e[r],e[a]]=[e[a],e[r]];}return e}(a).slice(0,e)}(e);return o.bus.send("search/showDefaultSearchKeywords",{keywords:a}),a})),o.bus.on("search/getDefaultSearchPois",(async({limit:r=5}={})=>{const a=await o.bus.get("poi/getAll"),t=e__namespace.pickBy(((e,r)=>e.isNavigable),a);return rand.arrayPick(Object.values(t),r)})),o.bus.on("search/registerSpecialQuery",(({term:e,event:r,params:a,addKeyword:s=!0})=>{c.indexesCreated.then((()=>{s&&c.typeahead.addKeyword(e),c.specialQueryTerms[e]={event:r,params:a};}));})),o.bus.on("search/addKeywords",(({keywords:e})=>c.indexesCreated.then((()=>e.forEach((e=>c.typeahead.addKeyword(e))))))),o.bus.on("search/typeahead",(({term:e,limit:r})=>c.indexesCreated.then((()=>{const{keywords:a,pois:s}=c.typeahead.query(e,r);return {keywords:a,pois:s,term:e}})))),o.bus.on("venueData/loadNewVenue",(()=>{c.indexesCreated=new a__default["default"],u();})),o.bus.on("poi/setDynamicData",(async({plugin:e,idValuesMap:r})=>{if("grab"!==e)return;const a=Object.keys(r).map((e=>o.bus.get("poi/getById",{id:e})));return Promise.all(a).then((e=>c.indexesCreated.then((()=>c.poiSearch.updateMultiple(e)))))}));return {init:u,runTest:async(e,r)=>(await r(),c)}}
35
+ function create (app, config) {
36
+ const state = {
37
+ poiSearch: null,
38
+ typeahead: null,
39
+ indexesCreated: new Zousan__default["default"](), // re-initialize this when changing venues
40
+ defaultSearchTerms: null,
41
+ specialQueryTerms: {}
42
+ };
36
43
 
37
- exports.create = o;
44
+ const init = async () => {
45
+ const pois = await app.bus.get('poi/getAll');
46
+ state.poiSearch = poiSearch(pois, app.i18n().language);
47
+ state.typeahead = searchTypeahead(pois, state.poiSearch.search, app.i18n().language);
48
+ state.defaultSearchTerms = configUtils.getLocalized(config, 'defaultSearchTerms', app.i18n().language);
49
+ state.indexesCreated.resolve();
50
+ };
51
+
52
+ /**
53
+ * Prepares and send an event with up to 50 non-portal POIs sorted by distance to user location.
54
+ */
55
+ // todo check if async events (events which send a new event as a result) are still needed
56
+ app.bus.on('search/queryNearby', async () => {
57
+ const pois = await searchNearby();
58
+ app.bus.send('search/showNearby', { pois, term: 'Nearby' });
59
+ return pois
60
+ });
61
+
62
+ /**
63
+ * Returns max 50 non-portal POIs sorted by distance to user location.
64
+ * @returns Array.<POI>
65
+ */
66
+ app.bus.on('search/queryNearbyAsync', searchNearby);
67
+
68
+ async function searchNearby () {
69
+ const startLocation = await app.bus.get('user/getPhysicalLocation');
70
+ if (!startLocation?.floorId) return []
71
+ const poisSameFloor = await app.bus.get('poi/getByFloorId', { floorId: startLocation?.floorId });
72
+ const isNotPortal = poi => poi.category.indexOf('portal') === -1 && poi.category !== 'element.door';
73
+ const noPortalPois = Object.values(R__namespace.pickBy(isNotPortal, poisSameFloor));
74
+ const poisWithDistance = await app.bus.get('wayfinder/addPathTimeMultiple', { pois: noPortalPois, startLocation });
75
+ return R__namespace.sortBy(R__namespace.prop('distance'), Object.values(poisWithDistance)).slice(0, 50)
76
+ }
77
+
78
+ /**
79
+ * Searches for POIs with search term or category name
80
+ * and sends a new event 'search/showCategory' with search result POIs.
81
+ *
82
+ * @param {string} searchTerm - term to search POIs
83
+ * @param {string} category - category name, fallback term to search POIs
84
+ * @param {string} categoryName - label to display in search results input view
85
+ */
86
+ app.bus.on('search/queryCategory', async ({ category, categoryName, searchTerm }) => {
87
+ const pois = await state.indexesCreated.then(() =>
88
+ state.poiSearch.search({ query: searchTerm || category }));
89
+ app.bus.send('search/showCategory', { pois, category, categoryName });
90
+ return pois
91
+ });
92
+
93
+ /**
94
+ * Searches for POIs with search term
95
+ * and sends a new event 'search/showCategory' with search result POIs.
96
+ *
97
+ * @param {string} term - search term
98
+ */
99
+ // todo introduce consistent naming for parameters are return values (searchTem or term, pois or results, keywords or searchTerms)
100
+ app.bus.on('search/query', ({ term }) => {
101
+ return state.indexesCreated.then(() => {
102
+ const pois = state.poiSearch.search({ query: term });
103
+ app.bus.send('search/showSearchResults', { results: pois, term });
104
+ return pois
105
+ })
106
+ });
107
+
108
+ /**
109
+ * Search for POIs with search term.
110
+ *
111
+ * @param {string} term - search term
112
+ * @returns Array.<POI>
113
+ */
114
+ app.bus.on('search/queryAsync', ({ term }) =>
115
+ state.indexesCreated.then(() => state.poiSearch.search({ query: term }))
116
+ );
117
+
118
+ /**
119
+ * If search term matches any registered special query term,
120
+ * then send an event with params for this special query,
121
+ * otherwise search for POIs with term and send the event 'search/query' with search result POIs
122
+ *
123
+ * @param {string} term - search term or special query
124
+ */
125
+ app.bus.on('search/queryWithSpecial', ({ term }) => {
126
+ if (state.specialQueryTerms[term]) {
127
+ const { event, params } = state.specialQueryTerms[term];
128
+ // use "send" as we can't gaurentee this event is a "get" or even returns POIs
129
+ return app.bus.send(event, params)
130
+ } else {
131
+ return app.bus.get('search/query', { term })
132
+ }
133
+ });
134
+
135
+ /**
136
+ * Returns list of all localized default search terms declared in the configuration
137
+ * or list of up to 'limit' random unique POI categories as a fallback.
138
+ * Returns a list of keywords and sends an event 'search/showDefaultSearchKeywords' with same the list of keywords.
139
+ *
140
+ * @param {number} [limit=5] - Used to limit number of random unique categories list if default search terms are not defined in configuration.
141
+ * @returns Array.<string> - list of keywords
142
+ */
143
+ app.bus.on('search/getDefaultSearchTerms', async ({ limit = 5 } = {}) => {
144
+ const defaultSearchTerms = state.defaultSearchTerms;
145
+ const hasDefaultSearchTerms = defaultSearchTerms && defaultSearchTerms.length;
146
+ const keywords = hasDefaultSearchTerms
147
+ ? defaultSearchTerms
148
+ : await getUniqueRandomCategories(limit);
149
+ app.bus.send('search/showDefaultSearchKeywords', { keywords });
150
+ return keywords
151
+ });
152
+
153
+ async function getUniqueRandomCategories (limit) {
154
+ const allCategories = (await app.bus.send('poi/getAllCategories'))[0];
155
+ const uniqueCategories = Array.from(new Set(allCategories));
156
+ const shuffledUniqueCategories = shuffle(uniqueCategories);
157
+ return shuffledUniqueCategories.slice(0, limit)
158
+ }
159
+
160
+ function shuffle (a) {
161
+ for (let i = a.length - 1; i > 0; i--) {
162
+ const j = Math.floor(Math.random() * (i + 1));
163
+ [a[i], a[j]] = [a[j], a[i]];
164
+ }
165
+ return a
166
+ }
167
+
168
+ /**
169
+ * Returns list of up to 'limit' unique random navigable POIs.
170
+ *
171
+ * @param {number} [limit=5]
172
+ * @returns Array.<POI>
173
+ */
174
+ app.bus.on('search/getDefaultSearchPois', async ({ limit = 5 } = {}) => {
175
+ const allPois = await app.bus.get('poi/getAll');
176
+ const navigablePred = (val, key) => val.isNavigable;
177
+ const navigablePois = R__namespace.pickBy(navigablePred, allPois);
178
+ return rand.arrayPick(Object.values(navigablePois), limit)
179
+ });
180
+
181
+ /**
182
+ * Registers an event and event params for special query term.
183
+ * Optionally adds passed special query term to keywords search index.
184
+ *
185
+ * @param {string} term - special query term
186
+ * @param {string} event - name of associated event
187
+ * @param {Object} params - parameters for associated event
188
+ * @param {boolean} addKeyword - indicates if term has to be added to keywords search index
189
+ */
190
+ app.bus.on('search/registerSpecialQuery', ({ term, event, params, addKeyword = true }) => {
191
+ state.indexesCreated.then(() => {
192
+ if (addKeyword) {
193
+ state.typeahead.addKeyword(term);
194
+ }
195
+ state.specialQueryTerms[term] = { event, params };
196
+ });
197
+ });
198
+
199
+ /**
200
+ * Adds list of keywords to keywords search index.
201
+ *
202
+ * @param {Array.<string>} keywords - list of new keywords
203
+ */
204
+ app.bus.on('search/addKeywords', ({ keywords }) =>
205
+ state.indexesCreated.then(() =>
206
+ keywords.forEach(keyword => state.typeahead.addKeyword(keyword))));
207
+
208
+ /**
209
+ * Returns lists of keywords and POIs matching search term.
210
+ *
211
+ * For term shorter than 3 characters only keywords index is queried.
212
+ * If no keywords are found or when term is longer,
213
+ * then POIs index is queried for the the remaining results.
214
+ *
215
+ * @param {string} term - search term
216
+ * @param {number} limit - maximum number of results
217
+ * @returns {{ pois: Array.<POI>, keywords: Array.<String>, term: string }} - list of keywords, list of POIs, search term
218
+ */
219
+ app.bus.on('search/typeahead', ({ term, limit }) => state.indexesCreated.then(() => {
220
+ const { keywords, pois } = state.typeahead.query(term, limit);
221
+ return { keywords, pois, term }
222
+ }));
223
+
224
+ /**
225
+ * Resets plugin state.
226
+ */
227
+ app.bus.on('venueData/loadNewVenue', () => {
228
+ state.indexesCreated = new Zousan__default["default"]();
229
+ init();
230
+ });
231
+
232
+ /**
233
+ * Updates POIs search index with dynamic Grab POIs.
234
+ *
235
+ * @param {string} plugin - type of dynamic data
236
+ * @param {Object<string, Object>} - dictionary of POI id to dynamic data object
237
+ */
238
+ app.bus.on('poi/setDynamicData', async ({ plugin, idValuesMap }) => {
239
+ if (plugin !== 'grab') return
240
+
241
+ const dynamicPoisPromises = Object.keys(idValuesMap)
242
+ .map(id => app.bus.get('poi/getById', { id }));
243
+
244
+ return Promise.all(dynamicPoisPromises)
245
+ .then(pois =>
246
+ state.indexesCreated.then(() =>
247
+ state.poiSearch.updateMultiple(pois)))
248
+ });
249
+
250
+ const runTest = async (initialState, testRoutine) => {
251
+ // state = { ...initialState }
252
+ await testRoutine();
253
+ return state
254
+ };
255
+
256
+ return {
257
+ init,
258
+ runTest
259
+ }
260
+ }
261
+
262
+ exports.create = create;
@@ -1,8 +1,65 @@
1
1
  'use strict';
2
2
 
3
- var e = require('ramda');
3
+ var R = require('ramda');
4
4
  var utils = require('./utils.js');
5
5
 
6
- function s(s,d,u){const c=function(s,d){const u=function(e){return Object.values(e).map((e=>e.category)).map((e=>e.split("."))).map((e=>e[0]))}(s),c=e.pipe(e.values,e.chain(e.prop("keywords")),e.filter(e.prop("isUserSearchable")),e.pluck("name"))(s),m=[...u,...c],p=Array.from(new Set([...m])),l=utils.getFlexSearchInstance({lang:d,type:"typeahead"});p.forEach(((e,r)=>l.add(r,e)));return {search:e=>l.search(e).map((e=>p[e])),add:e=>{p.push(e),l.add(p.length-1,e);}}}(s,u);return {query:(e,r)=>{const t=c.search({query:e,limit:r}),a=!(e.length<3)&&t.length,n=r-t.length,o=a?function(e,r){const t=d({query:e,limit:r}),a=d({query:e,suggest:!0,limit:r}),n=t.map((e=>e.poiId)),o=a.filter((e=>-1===n.indexOf(e.poiId)));return t.concat(o)}(e,n):[];return {keywords:t,pois:o}},addKeyword:e=>{c.add(e);}}}
6
+ function createSearchTypeahead (pois, poiSearch, lang) {
7
+ const suggestedKeywordsSearch = createSuggestedKeywordsSearch(pois, lang);
7
8
 
8
- module.exports = s;
9
+ function queryPois (query, limit) {
10
+ const matches = poiSearch({ query, limit });
11
+ const withSuggestions = poiSearch({ query, suggest: true, limit });
12
+ const matchedIds = matches.map(poi => poi.poiId);
13
+ const filteredSuggestions = withSuggestions.filter(poi => matchedIds.indexOf(poi.poiId) === -1);
14
+ return matches.concat(filteredSuggestions)
15
+ }
16
+
17
+ const query = (query, limit) => {
18
+ const suggestedKeywords = suggestedKeywordsSearch.search({ query, limit });
19
+ const queryLengthUnderLimit = query.length < 3;
20
+ const shouldQueryPois = !queryLengthUnderLimit && suggestedKeywords.length;
21
+ const poisLimit = limit - suggestedKeywords.length;
22
+ const pois = shouldQueryPois ? queryPois(query, poisLimit) : [];
23
+ return { keywords: suggestedKeywords, pois }
24
+ };
25
+
26
+ const addKeyword = (keyword) => {
27
+ suggestedKeywordsSearch.add(keyword);
28
+ };
29
+
30
+ return { query, addKeyword }
31
+ }
32
+
33
+ function createSuggestedKeywordsSearch (pois, lang) {
34
+ const categories = extractParentCategories(pois);
35
+ const poisKeywords = R.pipe(
36
+ R.values,
37
+ R.chain(R.prop('keywords')),
38
+ R.filter(R.prop('isUserSearchable')),
39
+ R.pluck('name')
40
+ )(pois);
41
+ const allPotentialKeywords = [...categories, ...poisKeywords];
42
+ const keywords = Array.from(new Set([...allPotentialKeywords]));
43
+ const index = utils.getFlexSearchInstance({ lang, type: 'typeahead' });
44
+
45
+ keywords.forEach((keyword, i) => index.add(i, keyword));
46
+
47
+ const search = (queryParams) => {
48
+ const ids = index.search(queryParams);
49
+ return ids.map(index => keywords[index])
50
+ };
51
+ const add = (newKeyword) => {
52
+ keywords.push(newKeyword);
53
+ index.add(keywords.length - 1, newKeyword);
54
+ };
55
+ return { search, add }
56
+ }
57
+
58
+ function extractParentCategories (pois) {
59
+ return Object.values(pois)
60
+ .map(poi => poi.category)
61
+ .map(fullCategory => fullCategory.split('.'))
62
+ .map(subcategories => subcategories[0])
63
+ }
64
+
65
+ module.exports = createSearchTypeahead;
@@ -2,12 +2,31 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var e = require('flexsearch');
5
+ var FlexSearch = require('flexsearch');
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
- var e__default = /*#__PURE__*/_interopDefaultLegacy(e);
9
+ var FlexSearch__default = /*#__PURE__*/_interopDefaultLegacy(FlexSearch);
10
10
 
11
- const n=["ko","ja","zh-Hans","zh-Hant"],r=({lang:r,type:t="standard"})=>{const s={tokenize:"forward",rtl:"ar"===r,stemmer:{s:"",es:"",ies:"y"}};return n.includes(r)&&(s.tokenize="full"),new e__default["default"].Index(s)};
11
+ const NON_ASCII_LANGUAGES = ['ko', 'ja', 'zh-Hans', 'zh-Hant'];
12
12
 
13
- exports.getFlexSearchInstance = r;
13
+ const getFlexSearchInstance = ({ lang, type = 'standard' }) => {
14
+ const options = {
15
+ tokenize: 'forward',
16
+ rtl: lang === 'ar', // only for arabic
17
+ stemmer: {
18
+ s: '',
19
+ es: '',
20
+ ies: 'y'
21
+ }
22
+ };
23
+
24
+ // Use the full tokenizer for non-ASCII languages and for standard searching
25
+ // but use "forward" for typeahead
26
+ if (NON_ASCII_LANGUAGES.includes(lang))
27
+ options.tokenize = 'full';
28
+
29
+ return new FlexSearch__default["default"].Index(options)
30
+ };
31
+
32
+ exports.getFlexSearchInstance = getFlexSearchInstance;