atriusmaps-node-sdk 1.0.0 → 3.2.28

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 (105) hide show
  1. package/README.md +76 -0
  2. package/config/rollup.config.cjs.js +31 -0
  3. package/dist/cjs/_virtual/_empty_module_placeholder.js +5 -0
  4. package/dist/cjs/deploy/nodeEntry.js +15 -0
  5. package/dist/cjs/deploy/prepareSDKConfig.js +9 -0
  6. package/dist/cjs/package.json +1 -0
  7. package/dist/cjs/package.json.js +11 -0
  8. package/dist/cjs/plugins/clientAPI/src/clientAPI.js +9 -0
  9. package/dist/cjs/plugins/dynamicPois/src/dynamicPois.js +33 -0
  10. package/dist/cjs/plugins/poiDataManager/src/poiDataManager.js +36 -0
  11. package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +31 -0
  12. package/dist/cjs/plugins/sdkServer/src/sdkServer.js +13 -0
  13. package/dist/cjs/plugins/sdkServer/src/util.js +10 -0
  14. package/dist/cjs/plugins/searchService/src/poiSearch.js +28 -0
  15. package/dist/cjs/plugins/searchService/src/searchService.js +37 -0
  16. package/dist/cjs/plugins/searchService/src/searchTypeahead.js +8 -0
  17. package/dist/cjs/plugins/searchService/src/utils.js +13 -0
  18. package/dist/cjs/plugins/venueDataLoader/src/venueDataLoader.js +36 -0
  19. package/dist/cjs/plugins/venueDataLoader/src/venueLoadingUtils.js +34 -0
  20. package/dist/cjs/plugins/wayfinder/src/findRoute.js +30 -0
  21. package/dist/cjs/plugins/wayfinder/src/minPriorityQueue.js +5 -0
  22. package/dist/cjs/plugins/wayfinder/src/navGraph.js +13 -0
  23. package/dist/cjs/plugins/wayfinder/src/navGraphDebug.js +30 -0
  24. package/dist/cjs/plugins/wayfinder/src/segmentBadges.js +5 -0
  25. package/dist/cjs/plugins/wayfinder/src/segmentBuilder.js +32 -0
  26. package/dist/cjs/plugins/wayfinder/src/segmentCategories.js +5 -0
  27. package/dist/cjs/plugins/wayfinder/src/stepBuilder.js +10 -0
  28. package/dist/cjs/plugins/wayfinder/src/wayfinder.js +40 -0
  29. package/dist/cjs/src/app.js +44 -0
  30. package/dist/cjs/src/auth/Auth.js +23 -0
  31. package/dist/cjs/src/configs/postproc-mol-url-parms.js +9 -0
  32. package/dist/cjs/src/configs/postproc-stateTracking.js +31 -0
  33. package/dist/cjs/src/configs/sdkHeadless.json.js +47 -0
  34. package/dist/cjs/src/controller.js +14 -0
  35. package/dist/cjs/src/debugTools.js +30 -0
  36. package/dist/cjs/src/env.js +7 -0
  37. package/dist/cjs/src/extModules/bustle.js +13 -0
  38. package/dist/cjs/src/extModules/flexapi/src/help.js +9 -0
  39. package/dist/cjs/src/extModules/flexapi/src/index.js +13 -0
  40. package/dist/cjs/src/extModules/flexapi/src/validate.js +10 -0
  41. package/dist/cjs/src/extModules/geohasher.js +8 -0
  42. package/dist/cjs/src/extModules/log.js +7 -0
  43. package/dist/cjs/src/historyManager.js +7 -0
  44. package/dist/cjs/src/utils/bounds.js +10 -0
  45. package/dist/cjs/src/utils/buildStructureLookup.js +29 -0
  46. package/dist/cjs/src/utils/configUtils.js +8 -0
  47. package/dist/cjs/src/utils/dom.js +10 -0
  48. package/dist/cjs/src/utils/funcs.js +15 -0
  49. package/dist/cjs/src/utils/geodesy.js +8 -0
  50. package/dist/cjs/src/utils/geom.js +35 -0
  51. package/dist/cjs/src/utils/i18n.js +14 -0
  52. package/dist/cjs/src/utils/observable.js +5 -0
  53. package/dist/cjs/src/utils/rand.js +8 -0
  54. package/lib/_virtual/_empty_module_placeholder.js +1 -0
  55. package/lib/deploy/nodeEntry.js +1 -58
  56. package/lib/deploy/prepareSDKConfig.js +1 -112
  57. package/lib/package.json.js +1 -143
  58. package/lib/plugins/clientAPI/src/clientAPI.js +1 -14
  59. package/lib/plugins/dynamicPois/src/dynamicPois.js +1 -131
  60. package/lib/plugins/poiDataManager/src/poiDataManager.js +1 -207
  61. package/lib/plugins/sdkServer/src/sdkHeadless.js +1 -53
  62. package/lib/plugins/sdkServer/src/sdkServer.js +1 -211
  63. package/lib/plugins/sdkServer/src/util.js +1 -18
  64. package/lib/plugins/searchService/src/poiSearch.js +1 -39
  65. package/lib/plugins/searchService/src/searchService.js +1 -234
  66. package/lib/plugins/searchService/src/searchTypeahead.js +1 -63
  67. package/lib/plugins/searchService/src/utils.js +1 -30
  68. package/lib/plugins/venueDataLoader/src/venueDataLoader.js +1 -465
  69. package/lib/plugins/venueDataLoader/src/venueLoadingUtils.js +1 -84
  70. package/lib/plugins/wayfinder/src/findRoute.js +1 -134
  71. package/lib/plugins/wayfinder/src/minPriorityQueue.js +1 -89
  72. package/lib/plugins/wayfinder/src/navGraph.js +1 -370
  73. package/lib/plugins/wayfinder/src/navGraphDebug.js +1 -95
  74. package/lib/plugins/wayfinder/src/segmentBadges.js +1 -29
  75. package/lib/plugins/wayfinder/src/segmentBuilder.js +1 -241
  76. package/lib/plugins/wayfinder/src/segmentCategories.js +1 -30
  77. package/lib/plugins/wayfinder/src/stepBuilder.js +1 -236
  78. package/lib/plugins/wayfinder/src/wayfinder.js +1 -452
  79. package/lib/src/app.js +1 -150
  80. package/lib/src/auth/Auth.js +1 -35
  81. package/lib/src/configs/postproc-mol-url-parms.js +1 -58
  82. package/lib/src/configs/postproc-stateTracking.js +1 -40
  83. package/lib/src/configs/sdkHeadless.json.js +1 -42
  84. package/lib/src/controller.js +1 -45
  85. package/lib/src/debugTools.js +1 -108
  86. package/lib/src/env.js +1 -17
  87. package/lib/src/extModules/bustle.js +1 -126
  88. package/lib/src/extModules/flexapi/src/help.js +1 -21
  89. package/lib/src/extModules/flexapi/src/index.js +1 -66
  90. package/lib/src/extModules/flexapi/src/validate.js +1 -131
  91. package/lib/src/extModules/geohasher.js +1 -90
  92. package/lib/src/extModules/log.js +1 -70
  93. package/lib/src/historyManager.js +1 -30
  94. package/lib/src/utils/bounds.js +1 -23
  95. package/lib/src/utils/buildStructureLookup.js +1 -17
  96. package/lib/src/utils/configUtils.js +1 -61
  97. package/lib/src/utils/dom.js +1 -46
  98. package/lib/src/utils/funcs.js +1 -50
  99. package/lib/src/utils/geodesy.js +1 -35
  100. package/lib/src/utils/geom.js +1 -141
  101. package/lib/src/utils/i18n.js +1 -70
  102. package/lib/src/utils/observable.js +1 -76
  103. package/lib/src/utils/rand.js +1 -82
  104. package/package.json +23 -6
  105. package/lib/_virtual/_empty_module_placeholder +0 -3
@@ -1,452 +1 @@
1
- import * as R from 'ramda';
2
- import Zousan from 'zousan';
3
- import { buildStructuresLookup } from '../../../src/utils/buildStructureLookup.js';
4
- import { distance } from '../../../src/utils/geodesy.js';
5
- import { findRoute } from './findRoute.js';
6
- import { createNavGraph } from './navGraph.js';
7
- import { enrichDebugNavGraph } from './navGraphDebug.js';
8
- import { buildSegments } from './segmentBuilder.js';
9
-
10
- const DEFAULT_WALKING_SPEED_M_PER_MIN = 60;
11
-
12
- const getEdgeTo = dst => node => R.find(e => e.dst === dst, node.edges);
13
-
14
- // todo may be not needed
15
- const SecurityLaneType = {
16
- SECURITY: 'SecurityLane',
17
- IMMIGRATION: 'ImmigrationLane'
18
- };
19
-
20
- /**
21
- * @typedef {Object} Endpoint
22
- * @property {number} lat - latitude
23
- * @property {number} lng - longitude
24
- * @property {string} title
25
- * @property {string} [floorId] - usually present
26
- * @property {number} [ordinal] - optional
27
- *
28
- * @typedef SecurityLaneIdsMap
29
- * @property {string[]} SecurityLane - list of ids of security lanes
30
- * @property {string[]} ImmigrationLane - list of ids of immigration lanes
31
- *
32
- * @typedef Route
33
- * @property {Step[]} steps - list of navigation steps
34
- * @property {Segment[]} segments - list of navigation line segments
35
- * @property {number} time - total route time
36
- * @property {number} distance - total route distance
37
- *
38
- * @typedef RouteOptions
39
- * @property {SecurityLaneIdsMap} selectedSecurityLanes - map of selected lane ids by type
40
- * @property {boolean} requiresAccessibility - true if route should be accessible
41
- * @property {boolean} compareFindPaths - indicate whether to calculate path using 2 methods and then compare their performance
42
- *
43
- * @typedef SecurityWaitTime
44
- * @property {number} queueTime
45
- * @property {boolean} timeIsReal
46
- * @property {boolean} isTemporarilyClosed
47
- *
48
- * @typedef {Array<number>} Coordinate - pair of lng and lat
49
- *
50
- */
51
- function create (app, config) {
52
- const log = app.log.sublog('wayfinder');
53
- const init = async () => {
54
- app.bus.send('venueData/loadNavGraph');
55
- };
56
-
57
- let graphLoadedProm = new Zousan();
58
-
59
- /**
60
- * Returns nav graph object for testing purposes.
61
- * Result includes nav nodes, edges, functions to update dynamic data and calculate shortest paths
62
- *
63
- * @returns {Object}
64
- */
65
- app.bus.on('wayfinder/_getNavGraph', () => graphLoadedProm);
66
-
67
- /**
68
- * @typedef RawNavGraph
69
- * @property Array.<RawNavEdge> edges
70
- * @property Array.<RawNavNode> nodes
71
- *
72
- * @typedef RawNavEdge
73
- * @property {string} s - id of start node
74
- * @property {string} d - id of destination node
75
- * @property {number} l - custom transit time
76
- * @property {boolean} h - is edge a driveway
77
- * @property {string} t - edge type
78
- * @property {Array.<{ s, o, i, e }>|null} p - list of Bezier points
79
- *
80
- * @typedef RawNavNode
81
- * @property {string} id
82
- * @property {string} floorId
83
- * @property {number} lat
84
- * @property {number} lng
85
- *
86
- * Transforms raw nav graph data and list of structures
87
- * to nav graph object with functions to build shortest paths
88
- *
89
- * @param {RawNavGraph} navGraphData
90
- * @param {Array.<Structure>} structures
91
- */
92
- app.bus.on('venueData/navGraphLoaded', async ({ navGraphData, structures }) => {
93
- const structureLookup = buildStructuresLookup(structures);
94
- const securityLanesMap = await prepareSecurityLanes();
95
- const graph = createNavGraph(
96
- navGraphData,
97
- structureLookup.floorIdToOrdinal,
98
- structureLookup.floorIdToStructureId,
99
- securityLanesMap
100
- );
101
- graphLoadedProm.resolve(graph);
102
- });
103
-
104
- const prepareSecurityLanes = async () => {
105
- const securityPois = await app.bus.get('poi/getByCategoryId', { categoryId: 'security' });
106
- return R.pipe(R.map(getSecurityLane), R.filter(R.identity))(securityPois)
107
- };
108
-
109
- const getSecurityLane = poi => poi.queue && {
110
- type: R.path(['queue', 'queueType'], poi),
111
- id: R.path(['queue', 'queueSubtype'], poi)
112
- };
113
-
114
- /**
115
- * Returns a shortest path from user physical location to provided destination
116
- * and triggers rendering navigation line on the map
117
- *
118
- * @param {Endpoint} toEndpoint
119
- * @param {Boolean} requiresAccessibility
120
- * @param {SecurityLaneIdsMap} selectedSecurityLanes
121
- * @returns {Route}
122
- */
123
- app.bus.on('wayfinder/showNavLineFromPhysicalLocation', async ({ toEndpoint, selectedSecurityLanes = null, requiresAccessibility }) => {
124
- const physicalLocation = await app.bus.get('user/getPhysicalLocation');
125
- return navigateFromTo(physicalLocation, toEndpoint, { selectedSecurityLanes, requiresAccessibility, primary: true })
126
- });
127
-
128
- async function navigateFromTo (fromEndpoint, toEndpoint, options) {
129
- const route = await getRoute({ fromEndpoint, toEndpoint, options });
130
- if (route) {
131
- const { segments } = route;
132
- if (options.primary)
133
- app.bus.send('map/resetNavlineFeatures');
134
- app.bus.send('map/showNavlineFeatures', { segments, alternative: !options.primary });
135
- }
136
-
137
- return route
138
- }
139
-
140
- const poiIdToNavigationEndpoint = (id, floorIdToOrdinal) =>
141
- app.bus.get('poi/getById', { id })
142
- .then(poi => {
143
- if (poi && poi.position) {
144
- return poiToNavigationEndpoint(poi, floorIdToOrdinal)
145
- } else
146
- throw Error('Unknown POI ID ' + id)
147
- });
148
-
149
- /**
150
- * @busEvent wayfinder/getNavigationEndpoint
151
- *
152
- * Returns an object of the Endoint type.
153
- * wayfinding uses this structure to find the closest node
154
- * for shortestPath calculations, etc.
155
- * @param {Object} p - can be a POI (or similar) or a string with lat,lng[,floorId[,name]] or location defined as { latitutde, longitude [, floorId] [, title] }
156
- * @returns {Endpoint} navigational endpoint
157
- */
158
- async function getNavigationEndpoint (p) {
159
- return graphLoadedProm.then(graph => {
160
- if (!p)
161
- throw Error('wayfinder: Invalid endpoint definition', p)
162
-
163
- if (typeof p === 'number')
164
- return poiIdToNavigationEndpoint(p, graph.floorIdToOrdinal)
165
-
166
- if (typeof p === 'string') {
167
- if (p.match(/^\d+$/)) // single integer - assume its poi id
168
- return poiIdToNavigationEndpoint(parseInt(p), graph.floorIdToOrdinal)
169
-
170
- if (p.indexOf(',') > 0) { // lat,lng,floorId,desc format
171
- let [lat, lng, floorId, title] = p.split(',');
172
- if (!graph.floorIdToStructureId(floorId))
173
- throw Error('Unknown floorId in endpoint: ' + floorId)
174
- if (!title)
175
- title = 'Starting Point';
176
-
177
- return {
178
- lat: parseFloat(lat),
179
- lng: parseFloat(lng),
180
- ordinal: graph.floorIdToOrdinal(floorId),
181
- floorId,
182
- title
183
- }
184
- }
185
- }
186
-
187
- if (isEndpoint(p))
188
- return p
189
-
190
- if (p.latitude)
191
- return {
192
- lat: p.latitude,
193
- lng: p.longitude,
194
- floorId: p.floorId,
195
- ordinal: graph.floorIdToOrdinal(p.floorId),
196
- title: p.title
197
- }
198
-
199
- if (p.position && p.name) // looks like a POI or some other
200
- return poiToNavigationEndpoint(p, graph.floorIdToOrdinal)
201
-
202
- throw Error('Invalid start or end point: ' + p)
203
- })
204
- }
205
-
206
- const endpointProps = ['lat', 'lng', 'floorId', 'ordinal'];
207
- const isEndpoint = R.pipe(
208
- R.pick(endpointProps),
209
- R.keys,
210
- R.propEq('length', endpointProps.length),
211
- Boolean
212
- );
213
-
214
- const poiToNavigationEndpoint = (poi, floorIdToOrdinal) => ({
215
- lat: poi.position.latitude,
216
- lng: poi.position.longitude,
217
- floorId: poi.position.floorId,
218
- ordinal: floorIdToOrdinal(poi.position.floorId),
219
- title: poi.name
220
- });
221
-
222
- /**
223
- * Transforms provided data to endpoint type object
224
- *
225
- * @return {Endpoint} - navigation endpoint
226
- */
227
- app.bus.on('wayfinder/getNavigationEndpoint', ({ ep }) => getNavigationEndpoint(ep));
228
-
229
- /**
230
- * @typedef PathSecurityInfo
231
- * @property {boolean} routeExists
232
- * @property {boolean} [hasSecurity]
233
- * @property {boolean} [hasImmigration]
234
- *
235
- * Checks if there is a path between 2 endpoints which satisfies passed options
236
- * and if this path includes security and immigration lanes
237
- *
238
- * @param {Endpoint} fromEndpoint
239
- * @param {Endpoint} toEndpoint
240
- * @param {RouteOptions} options
241
- * @returns {PathSecurityInfo}
242
- */
243
- app.bus.on('wayfinder/checkIfPathHasSecurity', ({ fromEndpoint, toEndpoint, options = {} }) => graphLoadedProm
244
- .then(graph => {
245
- options.compareFindPaths = config.compareFindPaths;
246
- const route = findRoute(graph, fromEndpoint, toEndpoint, options);
247
-
248
- if (!route) return { routeExists: false }
249
-
250
- const queues = route.waypoints
251
- .filter(node =>
252
- R.pathEq(['securityLane', 'type'], SecurityLaneType.SECURITY, node) ||
253
- R.pathEq(['securityLane', 'type'], SecurityLaneType.IMMIGRATION, node));
254
- const containsSecurityLaneType = type => Boolean(route.waypoints.find(R.pathEq(['securityLane', 'type'], type)));
255
- return {
256
- routeExists: true,
257
- queues,
258
- hasSecurity: containsSecurityLaneType(SecurityLaneType.SECURITY),
259
- hasImmigration: containsSecurityLaneType(SecurityLaneType.IMMIGRATION)
260
- }
261
- }));
262
-
263
- app.bus.on('wayfinder/getRoute', getRoute);
264
-
265
- /**
266
- * @busEvent wayfinder/getRoute
267
- *
268
- * Builds the shortest path between 2 endpoints which satisfies passed options
269
- *
270
- * @param {RouteOptions} options
271
- * @param {Endpoint} fromEndpoint
272
- * @param {Endpoint} toEndpoint
273
- *
274
- * @return {(Route|null)} route - route or null if no route available
275
- */
276
- async function getRoute ({ fromEndpoint, toEndpoint, options = {} }) {
277
- return graphLoadedProm
278
- .then(async graph => {
279
- options.compareFindPaths = config.compareFindPaths;
280
- const route = findRoute(graph, fromEndpoint, toEndpoint, options);
281
- if (!route) return null
282
- sendRouteAnalytic(fromEndpoint, toEndpoint, route); // todo move to analytics (NOTE: we call this twice for each nav, doubling stats!)
283
- const floorIdToNameMap = await app.bus.get('venueData/getFloorIdToNameMap');
284
- const queueTypes = await app.bus.get('venueData/getQueueTypes');
285
- const translate = app.gt();
286
- const { steps, segments } = buildSegments(
287
- route.waypoints,
288
- fromEndpoint,
289
- toEndpoint,
290
- floorIdToNameMap,
291
- translate,
292
- queueTypes);
293
-
294
- log.info('route', route);
295
- const time = Math.round(route.waypoints.reduce((total, { eta }) => total + eta, 0));
296
- const distance = Math.round(route.waypoints.reduce((total, { distance }) => total + distance, 0));
297
- return { ...route, segments, steps, time, distance }
298
- })
299
- }
300
-
301
- const sendRouteAnalytic = (start, end, navigationPath) => app.bus.send('session/submitEvent', {
302
- type: 'navigation',
303
- startPosition: {
304
- venueId: start.floorId.split('-')[0],
305
- buildingId: navigationPath.waypoints[0].position.structureId,
306
- floorId: navigationPath.waypoints[0].position.floorId,
307
- lat: navigationPath.waypoints[0].position.lat,
308
- lng: navigationPath.waypoints[0].position.lng
309
- },
310
- endPosition: {
311
- venueId: end.floorId.split('-')[0],
312
- buildingId: navigationPath.waypoints[navigationPath.waypoints.length - 1].position.structureId,
313
- floorId: navigationPath.waypoints[navigationPath.waypoints.length - 1].position.floorId,
314
- lat: navigationPath.waypoints[navigationPath.waypoints.length - 1].position.lat,
315
- lng: navigationPath.waypoints[navigationPath.waypoints.length - 1].position.lng
316
- }
317
- });
318
-
319
- /**
320
- * Calculates transit time and distance of shortest path to start location which satisfies passed options
321
- * and returns copy of POI with these new properties
322
- *
323
- * @param {Endpoint} startLocation
324
- * @param {RouteOptions} options
325
- * @returns {Object} - POI
326
- */
327
- app.bus.on('wayfinder/addPathTimeSingle', async ({ poi, startLocation, options = {} }) => {
328
- if (!startLocation) return poi
329
- return graphLoadedProm.then(graph => addPathTimeSingle(graph, options, poi, startLocation))
330
- });
331
-
332
- function addPathTimeSingle (graph, options, poi, start) {
333
- const end = poiToNavigationEndpoint(poi, graph.floorIdToOrdinal);
334
-
335
- const path = graph.findShortestPath(start, end, options);
336
-
337
- if (!path) {
338
- poi = getPoiWithGeoDistance(poi, start);
339
- poi.transitTime = poi.distance / DEFAULT_WALKING_SPEED_M_PER_MIN;
340
- return poi
341
- }
342
- return Object.assign(poi, { transitTime: pathTime(path), distance: pathDistance(path) })
343
- }
344
-
345
- /**
346
- * Calculates transit time and distance of shortest path from each POI to start location which satisfies passed options
347
- * and returns list of copies of POI with these new properties
348
- *
349
- * @param {Endpoint} startLocation
350
- * @param {RouteOptions} options
351
- * @param pois: array of pois
352
- * @returns Array.<Object> - list of POIs
353
- */
354
- app.bus.on('wayfinder/addPathTimeMultiple', async ({ pois, startLocation, options = {} }) => {
355
- if (!startLocation) return pois
356
- return graphLoadedProm.then(graph => addPathTimeMultiple(graph, options, pois, startLocation))
357
- });
358
-
359
- function addPathTimeMultiple (graph, options, pois, start) {
360
- const poiLocations = pois.map(poi => poiToNavigationEndpoint(poi, graph.floorIdToOrdinal));
361
- const paths = graph.findAllShortestPaths(start, poiLocations, options);
362
- return pois
363
- .map((poi, i) => resolveAndAddPathProps(poi, paths[i], start))
364
- }
365
-
366
- function resolveAndAddPathProps (poi, path, startLocation) {
367
- if (path && path.length) {
368
- poi = Object.assign(poi, { transitTime: pathTime(path), distance: pathDistance(path) });
369
- } else {
370
- poi = getPoiWithGeoDistance(poi, startLocation);
371
- poi.transitTime = poi.distance / DEFAULT_WALKING_SPEED_M_PER_MIN;
372
- }
373
- return poi
374
- }
375
-
376
- function pathTime (path) {
377
- return calculateTotalPathProperty(path, 'transitTime')
378
- }
379
-
380
- function pathDistance (path) {
381
- return calculateTotalPathProperty(path, 'distance')
382
- }
383
-
384
- function calculateTotalPathProperty (path, propertyName) {
385
- return R.aperture(2, path)
386
- .map(([from, to]) => getEdgeTo(to.id)(from))
387
- .map(R.prop(propertyName))
388
- .reduce((totalTime, edgeTime) => totalTime + edgeTime, 0)
389
- }
390
-
391
- function getPoiWithGeoDistance (poi, startLocation) {
392
- // todo should transitTime and distance be root poi properties?
393
- poi.distance = distance(
394
- startLocation.lat, startLocation.lng,
395
- poi.position.latitude, poi.position.longitude);
396
- return poi
397
- }
398
-
399
- /**
400
- * Resets plugin state
401
- */
402
- app.bus.on('venueData/loadNewVenue', () => {
403
- graphLoadedProm = new Zousan();
404
- init();
405
- });
406
-
407
- /**
408
- * Updates nav graph dynamic data if security data is passed
409
- *
410
- * @param {string} plugin - type of dynamic data
411
- * @param {Object<string, SecurityWaitTime|Object>} - dictionary of POI id to dynamic data object
412
- */
413
- app.bus.on('poi/setDynamicData', ({ plugin, idValuesMap }) => {
414
- if (plugin !== 'security') return
415
- graphLoadedProm.then(graph => graph.updateWithSecurityWaitTime(idValuesMap));
416
- });
417
-
418
- /**
419
- * Returns a list of edges and nodes in a format convenient to display them on the map
420
- *
421
- * @typedef DebugNode
422
- * @property {string} floorId
423
- * @property {string} id
424
- * @property {boolean} isOrphaned
425
- * @property {number} lat
426
- * @property {number} lng
427
- * @property {number} ordinal
428
- * @property {string} structureId
429
- *
430
- * @typedef DebugEdge
431
- * @property {Coordinate} startCoordinates
432
- * @property {Coordinate} endCoordinates
433
- * @property {boolean} isDriveway
434
- * @property {number} ordinal
435
- * @property {string} category
436
- * @property {string} defaultStrokeColor
437
- *
438
- * @returns {{nodes: DebugNode[], edges: DebugEdge[]}} debug nav graph
439
- */
440
- app.bus.on('wayfinder/getNavGraphFeatures', () => graphLoadedProm
441
- .then(({ _nodes }) => enrichDebugNavGraph(_nodes)));
442
-
443
- return {
444
- init,
445
- internal: {
446
- resolveNavGraph: graph => graphLoadedProm.resolve(graph),
447
- prepareSecurityLanes
448
- }
449
- }
450
- }
451
-
452
- export { SecurityLaneType, create };
1
+ import*as t from"ramda";import n from"zousan";import{buildStructuresLookup as o}from"../../../src/utils/buildStructureLookup.js";import{distance as e}from"../../../src/utils/geodesy.js";import{findRoute as i}from"./findRoute.js";import{createNavGraph as r}from"./navGraph.js";import{enrichDebugNavGraph as a}from"./navGraphDebug.js";import{buildSegments as s}from"./segmentBuilder.js";const u={SECURITY:"SecurityLane",IMMIGRATION:"ImmigrationLane"};function d(d,p){const l=d.log.sublog("wayfinder"),c=async()=>{d.bus.send("venueData/loadNavGraph")};let f=new n;d.bus.on("wayfinder/_getNavGraph",(()=>f)),d.bus.on("venueData/navGraphLoaded",(async({navGraphData:t,structures:n})=>{const e=o(n),i=await y(),a=r(t,e.floorIdToOrdinal,e.floorIdToStructureId,i);f.resolve(a)}));const y=async()=>{const n=await d.bus.get("poi/getByCategoryId",{categoryId:"security"});return t.pipe(t.map(m),t.filter(t.identity))(n)},m=n=>n.queue&&{type:t.path(["queue","queueType"],n),id:t.path(["queue","queueSubtype"],n)};d.bus.on("wayfinder/showNavLineFromPhysicalLocation",(async({toEndpoint:t,selectedSecurityLanes:n=null,requiresAccessibility:o})=>async function(t,n,o){const e=await b({fromEndpoint:t,toEndpoint:n,options:o});if(e){const{segments:t}=e;o.primary&&d.bus.send("map/resetNavlineFeatures"),d.bus.send("map/showNavlineFeatures",{segments:t,alternative:!o.primary})}return e}(await d.bus.get("user/getPhysicalLocation"),t,{selectedSecurityLanes:n,requiresAccessibility:o,primary:!0})));const g=(t,n)=>d.bus.get("poi/getById",{id:t}).then((o=>{if(o&&o.position)return w(o,n);throw Error("Unknown POI ID "+t)}));const I=["lat","lng","floorId","ordinal"],h=t.pipe(t.pick(I),t.keys,t.propEq("length",I.length),Boolean),w=(t,n)=>({lat:t.position.latitude,lng:t.position.longitude,floorId:t.position.floorId,ordinal:n(t.position.floorId),title:t.name});async function b({fromEndpoint:t,toEndpoint:n,options:o={}}){return f.then((async e=>{o.compareFindPaths=p.compareFindPaths;const r=i(e,t,n,o);if(!r)return null;v(t,n,r);const a=await d.bus.get("venueData/getFloorIdToNameMap"),u=await d.bus.get("venueData/getQueueTypes"),c=d.gt(),{steps:f,segments:y}=s(r.waypoints,t,n,a,c,u);l.info("route",r);const m=Math.round(r.waypoints.reduce(((t,{eta:n})=>t+n),0)),g=Math.round(r.waypoints.reduce(((t,{distance:n})=>t+n),0));return{...r,segments:y,steps:f,time:m,distance:g}}))}d.bus.on("wayfinder/getNavigationEndpoint",(({ep:t})=>async function(t){return f.then((n=>{if(!t)throw Error("wayfinder: Invalid endpoint definition",t);if("number"==typeof t)return g(t,n.floorIdToOrdinal);if("string"==typeof t){if(t.match(/^\d+$/))return g(parseInt(t),n.floorIdToOrdinal);if(t.indexOf(",")>0){let[o,e,i,r]=t.split(",");if(!n.floorIdToStructureId(i))throw Error("Unknown floorId in endpoint: "+i);return r||(r="Starting Point"),{lat:parseFloat(o),lng:parseFloat(e),ordinal:n.floorIdToOrdinal(i),floorId:i,title:r}}}if(h(t))return t;if(t.latitude)return{lat:t.latitude,lng:t.longitude,floorId:t.floorId,ordinal:n.floorIdToOrdinal(t.floorId),title:t.title};if(t.position&&t.name)return w(t,n.floorIdToOrdinal);throw Error("Invalid start or end point: "+t)}))}(t))),d.bus.on("wayfinder/checkIfPathHasSecurity",(({fromEndpoint:n,toEndpoint:o,options:e={}})=>f.then((r=>{e.compareFindPaths=p.compareFindPaths;const a=i(r,n,o,e);if(!a)return{routeExists:!1};const s=n=>Boolean(a.waypoints.find(t.pathEq(["securityLane","type"],n)));return{routeExists:!0,queues:a.waypoints.filter((n=>t.pathEq(["securityLane","type"],u.SECURITY,n)||t.pathEq(["securityLane","type"],u.IMMIGRATION,n))),hasSecurity:s(u.SECURITY),hasImmigration:s(u.IMMIGRATION)}})))),d.bus.on("wayfinder/getRoute",b);const v=(t,n,o)=>d.bus.send("session/submitEvent",{type:"navigation",startPosition:{venueId:t.floorId.split("-")[0],buildingId:o.waypoints[0].position.structureId,floorId:o.waypoints[0].position.floorId,lat:o.waypoints[0].position.lat,lng:o.waypoints[0].position.lng},endPosition:{venueId:n.floorId.split("-")[0],buildingId:o.waypoints[o.waypoints.length-1].position.structureId,floorId:o.waypoints[o.waypoints.length-1].position.floorId,lat:o.waypoints[o.waypoints.length-1].position.lat,lng:o.waypoints[o.waypoints.length-1].position.lng}});function T(t){return S(t,"transitTime")}function E(t){return S(t,"distance")}function S(n,o){return t.aperture(2,n).map((([n,o])=>{return(e=o.id,n=>t.find((t=>t.dst===e),n.edges))(n);var e})).map(t.prop(o)).reduce(((t,n)=>t+n),0)}function L(t,n){return t.distance=e(n.lat,n.lng,t.position.latitude,t.position.longitude),t}return d.bus.on("wayfinder/addPathTimeSingle",(async({poi:t,startLocation:n,options:o={}})=>n?f.then((e=>function(t,n,o,e){const i=w(o,t.floorIdToOrdinal),r=t.findShortestPath(e,i,n);if(!r)return(o=L(o,e)).transitTime=o.distance/60,o;return Object.assign(o,{transitTime:T(r),distance:E(r)})}(e,o,t,n))):t)),d.bus.on("wayfinder/addPathTimeMultiple",(async({pois:t,startLocation:n,options:o={}})=>n?f.then((e=>function(t,n,o,e){try{const i=o.map((n=>w(n,t.floorIdToOrdinal))),r=t.findAllShortestPaths(e,i,n);return o.map(((t,n)=>function(t,n,o){n&&n.length?t=Object.assign(t,{transitTime:T(n),distance:E(n)}):(t=L(t,o)).transitTime=t.distance/60;return t}(t,r[n],e)))}catch(t){return l.error(t),o}}(e,o,t,n))):t)),d.bus.on("venueData/loadNewVenue",(()=>{f=new n,c()})),d.bus.on("poi/setDynamicData",(({plugin:t,idValuesMap:n})=>{"security"===t&&f.then((t=>t.updateWithSecurityWaitTime(n)))})),d.bus.on("wayfinder/getNavGraphFeatures",(()=>f.then((({_nodes:t})=>a(t))))),{init:c,internal:{resolveNavGraph:t=>f.resolve(t),prepareSecurityLanes:y}}}export{u as SecurityLaneType,d as create};
package/lib/src/app.js CHANGED
@@ -1,150 +1 @@
1
- import IObject from 'IObject';
2
- import queryString from 'query-string';
3
- import { map, mergeDeepRight } from 'ramda';
4
- import Zousan from 'zousan-plus';
5
- import pkg from '../package.json.js';
6
- import debugTools from './debugTools.js';
7
- import { buildEnv } from './env.js';
8
- import { create as create$1 } from './extModules/bustle.js';
9
- import { initLog } from './extModules/log.js';
10
- import init from './utils/i18n.js';
11
-
12
- async function setupPlugin (app, id, config) {
13
- let name = id;
14
- if (name.includes('/')) {
15
- const split = name.split('/');
16
- name = split[split.length - 1];
17
- }
18
- if (config.active !== undefined && config.active === false) { // if active is explicitly set to false
19
- app.log.info(`Plugin ${id} explicitly deativated`);
20
- return null
21
- }
22
- return import(`../plugins/${id}/src/${name}.js`)
23
- .then(pluginModule => {
24
- app.log.info(`Creating plugin ${id}`);
25
- return pluginModule.create(app, config)
26
- })
27
- }
28
-
29
- // takes the `lang` query parameter and returns the most specific supported language
30
- // Recognizes the following optional configuration parameters:
31
- // supportedLanguages : array of supported language strings. i.e. [ "en", "en-US", "fr", "ja" ]
32
- // defaultLanguage : if all fails, use this language. default = "en"
33
- const getLang = config => {
34
- const supportedLanguages = config.supportedLanguages || ['ar', 'en', 'es', 'fr', 'ja', 'ko', 'zh-Hans', 'zh-Hant'];
35
-
36
- if (typeof window !== 'undefined') { // if this is a browser...
37
- const queryParms = queryString.parse(location.search);
38
- // eslint-disable-next-line no-constant-condition
39
- let lang = queryParms.lang || (typeof navigator ? navigator.language : null);
40
-
41
- while (lang)
42
- if (lang && supportedLanguages.includes(lang))
43
- return lang
44
- else
45
- lang = lang.substring(0, lang.lastIndexOf('-'));
46
- }
47
-
48
- return config.defaultLanguage || 'en'
49
- };
50
-
51
- async function extendConfig (config, extendsConfigs) {
52
- let newConfig = {};
53
- const extConfigFiles = await Promise.all(extendsConfigs.map(extConfigName => import(`./configs/${extConfigName}.json`)));
54
- for (const extendsConfigMod of extConfigFiles) {
55
- let extendsConfig = extendsConfigMod.default;
56
- extendsConfig = extendsConfig.extends ? await extendConfig(extendsConfig, extendsConfig.extends) : extendsConfig; // enable recursive extends
57
- newConfig = mergeDeepRight(newConfig, extendsConfig); // default is JSON data in ES6 modules import
58
- }
59
- newConfig = mergeDeepRight(newConfig, config);
60
- return newConfig
61
- }
62
-
63
- // const isSimpleName = name => /^[-a-zA-Z0-9]+$/.test(name) // composed of only alphanumeric and dash
64
-
65
- const createPostProcessor = name =>
66
- config => import(`./configs/postproc-${name}.js`)
67
- .then(pp => pp.process(config));
68
-
69
- const handleConfigPostProcess = async config =>
70
- config.configPostProc
71
- ? Zousan.series(config, ...config.configPostProc.map(createPostProcessor))
72
- : config;
73
-
74
- async function create (rawConfig) {
75
- const appInstance = Object.create(null);
76
-
77
- let config = rawConfig.extends ? await extendConfig(rawConfig, rawConfig.extends) : rawConfig;
78
-
79
- if (config.plugins.monitoring)
80
- import('../_virtual/_empty_module_placeholder').then(mon => mon.activate(config));
81
-
82
- config = await handleConfigPostProcess(config);
83
-
84
- const lang = getLang(config);
85
- const i18n = await init(lang, config.debug);
86
- appInstance.i18n = () => i18n;
87
- appInstance.gt = () => i18n.t.bind(i18n); // get translation function - don't hold this, it is bound to current lang
88
-
89
- appInstance.config = config;
90
-
91
- appInstance.plugins = new IObject();
92
- const isBrowser = typeof window !== 'undefined';
93
- const appLog = initLog('web-engine', { enabled: !!config.debug, isBrowser, color: 'cyan', logFilter: config.logFilter, truncateObjects: !isBrowser });
94
-
95
- appInstance.log = appLog.sublog(config.name);
96
- appInstance.bus = create$1({ trace: false, showEvents: true, reportAllErrors: true, log: appLog });
97
-
98
- appInstance.info = { wePkg: pkg }; // web-engine package
99
-
100
- if (typeof window !== 'undefined') { // Prepare for non-browser environments
101
- if (config.debug) {
102
- appInstance.debug = map(fn => fn.bind(appInstance), debugTools);
103
- debugTools.dndGo.call(appInstance); // setup DnD by default...
104
- } else
105
- appInstance.debug = { }; // no tools unless in debug mode.. (good idea?)
106
-
107
- window._app = appInstance;
108
- if (window.document && window.document.title)
109
- document.title = config.name;
110
- }
111
-
112
- appInstance.env = buildEnv(appInstance);
113
-
114
- if (config.theme) { // the following is only needed when UI is active - which requires a theme
115
- await Zousan.evaluate(
116
- { name: 'ThemeManagerModule', value: import('../_virtual/_empty_module_placeholder') },
117
- { name: 'HistoryManager', value: import('./historyManager.js') },
118
- { name: 'LayerManager', value: import('../_virtual/_empty_module_placeholder') }
119
- ).then(async ({ LayerManager, HistoryManager, ThemeManagerModule }) => {
120
- const ThemeManager = ThemeManagerModule.initThemeManager(appInstance);
121
- appInstance.themePack = await ThemeManager.buildTheme(config.theme, config.defaultTheme);
122
-
123
- LayerManager.initLayerManager(appInstance);
124
- HistoryManager.initHistoryManager(appInstance);
125
- });
126
- }
127
-
128
- if (config.plugins) {
129
- for (const id in config.plugins) {
130
- try {
131
- const pluginConfig = config.plugins[id];
132
- if (appInstance.plugins[id]) { throw Error(`Duplicate plugin name "${id}"`) }
133
- const plugin = await setupPlugin(appInstance, id, pluginConfig);
134
- if (plugin)
135
- appInstance.plugins = appInstance.plugins.set(id, plugin);
136
- } catch (e) {
137
- appLog.error('Error instantiating plugin ' + id);
138
- appLog.error(e);
139
- }
140
- }
141
-
142
- for (const id in appInstance.plugins) {
143
- appInstance.plugins[id].init();
144
- }
145
- }
146
-
147
- return appInstance
148
- }
149
-
150
- export { create };
1
+ import e from"IObject";import t from"query-string";import{map as n,mergeDeepRight as o}from"ramda";import i from"zousan-plus";import r from"../package.json.js";import a from"./debugTools.js";import{buildEnv as s}from"./env.js";import{create as l}from"./extModules/bustle.js";import{initLog as u}from"./extModules/log.js";import c from"./utils/i18n.js";const g="undefined"!=typeof window;async function p(e,t,n){let o=t;if(o.includes("/")){const e=o.split("/");o=e[e.length-1]}return void 0!==n.active&&!1===n.active?(e.log.info(`Plugin ${t} explicitly deativated`),null):import(`../plugins/${t}/src/${o}.js`).then((o=>(e.log.info(`Creating plugin ${t}`),o.create(e,n))))}async function d(e){return g?import(`./configs/${e}.json`):import(`./configs/${e}.json.js`)}async function m(e,t){let n={};const i=await Promise.all(t.map(d));for(const e of i){let t=e.default;t=t.extends?await m(t,t.extends):t,n=o(n,t)}return n=o(n,e),n}const f=e=>t=>import(`./configs/postproc-${e}.js`).then((e=>e.process(t)));async function w(o){const d=Object.create(null);let w=o.extends?await m(o,o.extends):o;w.plugins.monitoring&&import("../_virtual/_empty_module_placeholder.js").then((e=>e.activate(w))),w=await(async e=>e.configPostProc?i.series(e,...e.configPostProc.map(f)):e)(w);const y=(e=>{const n=e.supportedLanguages||["ar","en","es","fr","ja","ko","zh-Hans","zh-Hant"];if("undefined"!=typeof window){let e=t.parse(location.search).lang||navigator.language;for(;e;){if(e&&n.includes(e))return e;e=e.substring(0,e.lastIndexOf("-"))}}return e.defaultLanguage||"en"})(w),h=await c(y,w.debug);d.i18n=()=>h,d.gt=()=>h.t.bind(h),d.config=w,d.plugins=new e;const j=u("web-engine",{enabled:!!w.debug,isBrowser:g,color:"cyan",logFilter:w.logFilter,truncateObjects:!g});if(d.log=j.sublog(w.name),d.bus=l({trace:!1,showEvents:!0,reportAllErrors:!0,log:j}),d.info={wePkg:r},"undefined"!=typeof window&&(w.debug?(d.debug=n((e=>e.bind(d)),a),a.dndGo.call(d)):d.debug={},window._app=d,window.document&&window.document.title&&w.setWindowTitle&&(document.title=w.name)),d.env=s(d),w.theme?await i.evaluate({name:"ThemeManagerModule",value:import("../_virtual/_empty_module_placeholder.js")},{name:"HistoryManager",value:import("./historyManager.js")},{name:"LayerManager",value:import("../_virtual/_empty_module_placeholder.js")}).then((async({LayerManager:e,HistoryManager:t,ThemeManagerModule:n})=>{const o=n.initThemeManager(d);d.themePack=await o.buildTheme(w.theme,w.defaultTheme),e.initLayerManager(d),t.initHistoryManager(d),d.destroy=()=>e.destroy(d)})):d.destroy=()=>{},w.plugins){for(const e in w.plugins)try{const t=w.plugins[e];if(d.plugins[e])throw Error(`Duplicate plugin name "${e}"`);const n=await p(d,e,t);n&&(d.plugins=d.plugins.set(e,n))}catch(t){j.error("Error instantiating plugin "+e),j.error(t)}for(const e in d.plugins)d.plugins[e].init()}return d}export{w as create};
@@ -1,35 +1 @@
1
- async function Auth (authConfig, app) {
2
- const auth = await (async () => {
3
- if (!authConfig || !authConfig.type)
4
- throw Error('No authentication type found in config')
5
-
6
- const resolveAuthModuleName = config => {
7
- switch (config.type) {
8
- case 'ms': return 'MSAuth'
9
- case 'cognito': return 'CognitoAuth'
10
- case 'google': return 'GoogleAuth'
11
- default: throw Error(`Unknown auth type: '${config.type}'`)
12
- }
13
- };
14
-
15
- return Promise.resolve(resolveAuthModuleName(authConfig))
16
- .then(moduleName => import(`./${moduleName}`))
17
- .then(module => module.default(authConfig.config, app))
18
- })();
19
-
20
- const getToken = async () => auth.getToken();
21
-
22
- const isLoggedIn = async () => auth.isLoggedIn();
23
-
24
- const federatedLogin = async () => auth.federatedLogin();
25
-
26
- const logout = () => auth.logout();
27
-
28
- const getAccountInfo = () => auth.getAccountInfo();
29
-
30
- const getType = () => authConfig.type;
31
-
32
- return { getToken, isLoggedIn, federatedLogin, logout, getAccountInfo, getType }
33
- }
34
-
35
- export default Auth;
1
+ async function t(t,e){const o=await(async()=>{if(!t||!t.type)throw Error("No authentication type found in config");return Promise.resolve((t=>{switch(t.type){case"ms":return"MSAuth";case"cognito":return"CognitoAuth";case"google":return"GoogleAuth";default:throw Error(`Unknown auth type: '${t.type}'`)}})(t)).then((t=>import(`./${t}`))).then((o=>o.default(t.config,e)))})();return{getToken:async()=>o.getToken(),isLoggedIn:async()=>o.isLoggedIn(),federatedLogin:async()=>o.federatedLogin(),logout:()=>o.logout(),getAccountInfo:()=>o.getAccountInfo(),getType:()=>t.type}}export{t as default};