atriusmaps-node-sdk 3.3.1033 → 3.3.1035

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = "3.3.1033";
5
+ var version = "3.3.1035";
6
6
  var pkg = {
7
7
  version: version};
8
8
 
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ var operationHours = require('../../../src/utils/operationHours.js');
4
+ var constants = require('../../../utils/constants.js');
5
+
6
+ const SOON_THRESHOLD_MINUTES = 60;
7
+ function computeIsOpenNow(poi, venueTimezone, now = /* @__PURE__ */ new Date()) {
8
+ if (poi.state === "permanently-closed") {
9
+ return false;
10
+ }
11
+ const dynamicStatus = poi.dynamicData?.["open-closed-status"];
12
+ if (dynamicStatus) {
13
+ const expiresAt = dynamicStatus.expiresAt;
14
+ if (expiresAt === void 0 || expiresAt > now.getTime()) {
15
+ return dynamicStatus.isOpen;
16
+ }
17
+ }
18
+ if (!venueTimezone) {
19
+ return void 0;
20
+ }
21
+ if (!operationHours.canParseOperationHours(poi.operationHours)) {
22
+ return void 0;
23
+ }
24
+ const localizedNow = operationHours.toLocalDate(now, venueTimezone);
25
+ const weekdayPeriods = operationHours.parseAndOrderWeekdays(poi.operationHours, localizedNow);
26
+ if (!weekdayPeriods || weekdayPeriods.length === 0) {
27
+ return void 0;
28
+ }
29
+ return operationHours.isOpen(weekdayPeriods, localizedNow);
30
+ }
31
+ function computePoiOpenStatus(poi, venueTimezone, T, now = /* @__PURE__ */ new Date()) {
32
+ const openNow = computeIsOpenNow(poi, venueTimezone, now);
33
+ if (openNow === void 0) {
34
+ return void 0;
35
+ }
36
+ const status = resolveStatus(poi, venueTimezone, openNow, now);
37
+ const timeLabel = venueTimezone ? operationHours.getOpenTimeLabel(poi.operationHours, now, T, venueTimezone) || void 0 : void 0;
38
+ return { isOpen: openNow, status, timeLabel };
39
+ }
40
+ function resolveStatus(poi, venueTimezone, openNow, now) {
41
+ const plainStatus = openNow ? constants.PoiOpenStatus.OPEN : constants.PoiOpenStatus.CLOSED;
42
+ if (!venueTimezone || !operationHours.canParseOperationHours(poi.operationHours)) {
43
+ return plainStatus;
44
+ }
45
+ const localizedNow = operationHours.toLocalDate(now, venueTimezone);
46
+ const weekdayPeriods = operationHours.parseAndOrderWeekdays(poi.operationHours, localizedNow);
47
+ if (!weekdayPeriods || weekdayPeriods.length === 0) {
48
+ return plainStatus;
49
+ }
50
+ const { minutesToOpen, minutesToClose } = operationHours.getBoundaryMinutes(weekdayPeriods, localizedNow);
51
+ if (openNow) {
52
+ return isWithinThreshold(minutesToClose) ? constants.PoiOpenStatus.CLOSING_SOON : constants.PoiOpenStatus.OPEN;
53
+ }
54
+ return isWithinThreshold(minutesToOpen) ? constants.PoiOpenStatus.OPENING_SOON : constants.PoiOpenStatus.CLOSED;
55
+ }
56
+ function isWithinThreshold(minutes) {
57
+ return minutes !== void 0 && minutes > 0 && minutes <= SOON_THRESHOLD_MINUTES;
58
+ }
59
+
60
+ exports.computeIsOpenNow = computeIsOpenNow;
61
+ exports.computePoiOpenStatus = computePoiOpenStatus;
@@ -5,6 +5,7 @@ var Zousan = require('zousan');
5
5
  var buildStructureLookup = require('../../../src/utils/buildStructureLookup.js');
6
6
  var configUtils = require('../../../src/utils/configUtils.js');
7
7
  var i18n = require('../../../src/utils/i18n.js');
8
+ var computeIsOpenNow = require('./computeIsOpenNow.js');
8
9
 
9
10
  function _interopNamespaceDefault(e) {
10
11
  var n = Object.create(null);
@@ -25,8 +26,9 @@ function _interopNamespaceDefault(e) {
25
26
 
26
27
  var R__namespace = /*#__PURE__*/_interopNamespaceDefault(R);
27
28
 
28
- async function create(app) {
29
+ async function create(app, config) {
29
30
  const log = app.log.sublog("poiDataManager");
31
+ const isOpenStatusEnabled = config?.enableOpenStatus === true;
30
32
  const init = () => {
31
33
  app.bus.send("venueData/loadPoiData");
32
34
  };
@@ -177,6 +179,18 @@ async function create(app) {
177
179
  return poisLoaded.then(R__namespace.pickBy(categoryMatch));
178
180
  });
179
181
  app.bus.on("poi/getAll", async () => poisLoaded);
182
+ app.bus.on("poi/getOpenStatus", async ({ id, now }) => {
183
+ if (!isOpenStatusEnabled) {
184
+ return void 0;
185
+ }
186
+ const pois = await poisLoaded;
187
+ const poi = pois[id];
188
+ if (!poi) {
189
+ return void 0;
190
+ }
191
+ const venueTimezone = await app.bus.get("venueData/getVenueTimezone");
192
+ return computeIsOpenNow.computePoiOpenStatus(poi, venueTimezone, app.gt(), now ?? /* @__PURE__ */ new Date());
193
+ });
180
194
  const checkpointPath = ["queue", "primaryQueueId"];
181
195
  const addOtherSecurityLanesIfNeeded = async (poi) => {
182
196
  const primaryCheckpointId = R__namespace.path(checkpointPath, poi);
@@ -252,15 +266,14 @@ async function create(app) {
252
266
  poisLoaded = new Zousan();
253
267
  init();
254
268
  });
255
- app.bus.on("poi/setDynamicData", ({ plugin, idValuesMap }) => {
256
- poisLoaded.then((pois) => {
257
- for (const poiId in idValuesMap) {
258
- const dynamicData = pois[poiId].dynamicData || {};
259
- dynamicData[plugin] = { ...idValuesMap[poiId] };
260
- const newPoi = R__namespace.mergeRight(pois[poiId], { dynamicData });
261
- pois[poiId] = newPoi;
262
- }
263
- });
269
+ app.bus.on("poi/setDynamicData", async ({ plugin, idValuesMap }) => {
270
+ const pois = await poisLoaded;
271
+ for (const poiId in idValuesMap) {
272
+ const dynamicData = pois[poiId].dynamicData || {};
273
+ dynamicData[plugin] = { ...idValuesMap[poiId] };
274
+ const newPoi = R__namespace.mergeRight(pois[poiId], { dynamicData });
275
+ pois[poiId] = newPoi;
276
+ }
264
277
  });
265
278
  app.bus.on("poi/setCoreAttributes", (idAttributesMap) => {
266
279
  poisLoaded.then((pois) => {
@@ -0,0 +1,300 @@
1
+ 'use strict';
2
+
3
+ var luxon = require('luxon');
4
+ var R = require('ramda');
5
+
6
+ function _interopNamespaceDefault(e) {
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var R__namespace = /*#__PURE__*/_interopNamespaceDefault(R);
24
+
25
+ function canParseOperationHours(operationHours) {
26
+ if (!operationHours || typeof operationHours !== "string") {
27
+ return false;
28
+ }
29
+ const trimmed = operationHours.trim();
30
+ if (trimmed === "") {
31
+ return false;
32
+ }
33
+ const validDayPattern = /^(Su|Mo|Tu|We|Th|Fr|Sa)(-(?:Su|Mo|Tu|We|Th|Fr|Sa))?\s+\d{1,2}:\d{2}-\d{1,2}:\d{2}$/;
34
+ const segments = trimmed.split(";").map((s) => s.trim());
35
+ return segments.every((segment) => validDayPattern.test(segment));
36
+ }
37
+ function isOpen(weekdayPeriods, today) {
38
+ const currentWeekday = findWeekday(weekdayPeriods, today);
39
+ if (!currentWeekday) {
40
+ return false;
41
+ }
42
+ const hours = today.getHours();
43
+ const minutes = today.getMinutes();
44
+ const { from, to } = currentWeekday.timePeriod;
45
+ return isInTimePeriod(hours, minutes, from.hours, from.minutes, to.hours, to.minutes);
46
+ }
47
+ function getBoundaryMinutes(weekdayPeriods, localizedNow) {
48
+ const currentWeekday = findWeekday(weekdayPeriods, localizedNow);
49
+ if (!currentWeekday) {
50
+ return { minutesToOpen: void 0, minutesToClose: void 0 };
51
+ }
52
+ return {
53
+ minutesToOpen: minutesBetweenDateTimeAndWeekdayTime(localizedNow, currentWeekday.timePeriod.from),
54
+ minutesToClose: minutesBetweenDateTimeAndWeekdayTime(localizedNow, currentWeekday.timePeriod.to)
55
+ };
56
+ }
57
+ function isInTimePeriod(nowHours, nowMinutes, fromHours, fromMinutes, toHours, toMinutes) {
58
+ const isOvernightPeriod = isFirstTimeAfterSecond(fromHours, fromMinutes, toHours, toMinutes);
59
+ if (isOvernightPeriod) {
60
+ return isInTimePeriod(nowHours, nowMinutes, fromHours, fromMinutes, 24, 0) || isInTimePeriod(nowHours, nowMinutes, 0, 0, toHours, toMinutes);
61
+ } else {
62
+ const isAfterFrom = isFirstTimeAfterSecond(nowHours, nowMinutes, fromHours, fromMinutes);
63
+ const isBeforeTo = isFirstTimeAfterSecond(toHours, toMinutes, nowHours, nowMinutes);
64
+ return isAfterFrom && isBeforeTo;
65
+ }
66
+ }
67
+ function isFirstTimeAfterSecond(firstHours, firstMinutes, secondHours, secondMinutes) {
68
+ return firstHours > secondHours || firstHours === secondHours && firstMinutes >= secondMinutes;
69
+ }
70
+ function findWeekday(weekdayPeriods, today) {
71
+ return findWeekdayByDayIndex(weekdayPeriods, today.getDay());
72
+ }
73
+ function findWeekdayByDayIndex(weekdayPeriods, index) {
74
+ const currentWeekdayName = WEEKDAY_ARRAY[index];
75
+ return weekdayPeriods.find(({ weekday }) => weekday === currentWeekdayName);
76
+ }
77
+ function parseAndOrderWeekdays(rawWeekdayPeriods, today) {
78
+ const weekdays = parseWeekdayPeriods(rawWeekdayPeriods);
79
+ const orderedWeekdays = orderFromSunday(weekdays);
80
+ return markCurrentWeekday(orderedWeekdays, today);
81
+ }
82
+ const SHORT_WEEKDAY_TO_NUMERAL = {
83
+ Su: 0,
84
+ Mo: 1,
85
+ Tu: 2,
86
+ We: 3,
87
+ Th: 4,
88
+ Fr: 5,
89
+ Sa: 6
90
+ };
91
+ const WEEKDAY_ARRAY = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
92
+ const WEEKDAY_TO_NUMERAL = WEEKDAY_ARRAY.reduce(
93
+ (obj, weekday, index) => Object.assign(obj, { [weekday]: index }),
94
+ {}
95
+ );
96
+ const WEEKDAYS_DELIMITER = ";";
97
+ const WEEKDAY_AND_TIME_DELIMITER = /\s+/;
98
+ const WEEKDAY_DELIMITER = "-";
99
+ const TIME_PERIOD_DELIMITER = "-";
100
+ const TIME_DELIMITER = ":";
101
+ const AM = " AM";
102
+ const PM = " PM";
103
+ function parseWeekdayPeriods(rawWeekdayPeriods) {
104
+ return rawWeekdayPeriods.split(WEEKDAYS_DELIMITER).map((weekdayAndTimePeriod) => weekdayAndTimePeriod.trim()).map((weekdayAndTimePeriod) => weekdayAndTimePeriod.split(WEEKDAY_AND_TIME_DELIMITER)).flatMap(([weekdayPeriod, timePeriod]) => {
105
+ const weekdays = parseWeekdayPeriod(weekdayPeriod);
106
+ const formattedTimePeriod = prepareTimePeriodData(timePeriod);
107
+ return createWeekdayAndTimePeriodPairs(weekdays, formattedTimePeriod);
108
+ });
109
+ }
110
+ function parseWeekdayPeriod(weekdayPeriod) {
111
+ const [start, end] = weekdayPeriod.split(WEEKDAY_DELIMITER);
112
+ const startIndex = SHORT_WEEKDAY_TO_NUMERAL[start];
113
+ let weekdayIndices;
114
+ if (end) {
115
+ const endIndex = SHORT_WEEKDAY_TO_NUMERAL[end];
116
+ weekdayIndices = weekdayIndicesRange(startIndex, endIndex);
117
+ } else {
118
+ weekdayIndices = [startIndex];
119
+ }
120
+ return weekdayIndices.map((index) => WEEKDAY_ARRAY[index]);
121
+ }
122
+ function weekdayIndicesRange(startIndex, endIndex) {
123
+ const weekdayIndices = [startIndex];
124
+ let currentDayIndex = startIndex;
125
+ do {
126
+ currentDayIndex = (currentDayIndex + 1) % WEEKDAY_ARRAY.length;
127
+ weekdayIndices.push(currentDayIndex);
128
+ } while (currentDayIndex !== endIndex);
129
+ return weekdayIndices;
130
+ }
131
+ function prepareTimePeriodData(timePeriod) {
132
+ const [from, to] = timePeriod.split(TIME_PERIOD_DELIMITER);
133
+ const [fromTime, fromTimeFormatted] = getHoursMinutesAndFormatted(from);
134
+ const [toTime, toTimeFormatted] = getHoursMinutesAndFormatted(to);
135
+ const timePeriodFormatted = fromTimeFormatted + ` ${TIME_PERIOD_DELIMITER} ` + toTimeFormatted;
136
+ return {
137
+ from: fromTime,
138
+ to: toTime,
139
+ formatted: timePeriodFormatted
140
+ };
141
+ }
142
+ function getHoursMinutesAndFormatted(time) {
143
+ const [hours, minutes] = time.split(TIME_DELIMITER);
144
+ const timeFormatted = formatTimeAmPm(hours, minutes);
145
+ return [{ hours: +hours, minutes: +minutes }, timeFormatted];
146
+ }
147
+ function formatTimeAmPm(hours, minutes) {
148
+ const hoursNum = +hours;
149
+ const minutesNum = +minutes;
150
+ const ampm = hoursNum < 12 || hoursNum === 24 ? AM : PM;
151
+ const displayHours = hoursNum % 12 || 12;
152
+ const minutesStr = minutesNum > 9 ? String(minutesNum) : "0" + minutesNum;
153
+ return displayHours + TIME_DELIMITER + minutesStr + ampm;
154
+ }
155
+ function createWeekdayAndTimePeriodPairs(weekdays, timePeriod) {
156
+ return weekdays.map((weekday) => ({ weekday, timePeriod }));
157
+ }
158
+ function orderFromSunday(weekdayPeriods) {
159
+ const startWeekdayIndex = 0;
160
+ const orderedWeekdays = [];
161
+ weekdayPeriods.forEach((weekday) => {
162
+ const weekdayIndex = WEEKDAY_TO_NUMERAL[weekday.weekday];
163
+ let order = weekdayIndex - startWeekdayIndex;
164
+ if (order < 0) {
165
+ order += WEEKDAY_ARRAY.length;
166
+ }
167
+ orderedWeekdays[order] = weekday;
168
+ });
169
+ return filterEmptyDays(orderedWeekdays);
170
+ }
171
+ function filterEmptyDays(weekdays) {
172
+ return weekdays.filter((x) => Boolean(x));
173
+ }
174
+ function markCurrentWeekday(weekdays, today) {
175
+ const todayDayName = WEEKDAY_ARRAY[today.getDay()];
176
+ const addIsToday = R__namespace.converge(R__namespace.assoc("isToday"), [R__namespace.propEq(todayDayName, "weekday"), R__namespace.identity]);
177
+ return weekdays.map((weekday) => addIsToday(weekday));
178
+ }
179
+ function getOpenTimeLabel(operationHours, nowDate, T, timezone) {
180
+ if (operationHours === "Mo-Su 00:00-24:00") {
181
+ return T("ui:Always open");
182
+ }
183
+ if (!operationHours) {
184
+ return "";
185
+ }
186
+ if (!canParseOperationHours(operationHours)) {
187
+ return "";
188
+ }
189
+ const localizedDate = toLocalDate(nowDate, timezone);
190
+ const weekdayPeriods = parseAndOrderWeekdays(operationHours, localizedDate);
191
+ if (!weekdayPeriods) {
192
+ return "";
193
+ }
194
+ const currentWeekday = findWeekday(weekdayPeriods, localizedDate);
195
+ if (!currentWeekday || compareDateTimeAndWeekdayTime(localizedDate, currentWeekday.timePeriod.to) === -1) {
196
+ return prepareTimeToNextWorkingDay(localizedDate, weekdayPeriods, T);
197
+ }
198
+ if (isDateInWeekdayOpenHours(localizedDate, currentWeekday)) {
199
+ return prepareTimeToTodayClose(localizedDate, currentWeekday, T);
200
+ }
201
+ return prepareTimeToTodayOpen(localizedDate, currentWeekday, T);
202
+ }
203
+ function toLocalDate(date, timezone) {
204
+ const { year, month, day, hour, minute } = luxon.DateTime.fromJSDate(date, {
205
+ zone: timezone ?? void 0
206
+ });
207
+ return new Date(year, month - 1, day, hour, minute);
208
+ }
209
+ function prepareTimeToNextWorkingDay(nowDate, weekdayPeriods, T) {
210
+ const tomorrowDate = getNextDayDate(nowDate);
211
+ const nextWeekday = findWeekday(weekdayPeriods, tomorrowDate);
212
+ if (nextWeekday) {
213
+ const minutesToTomorrowOpen = minutesBetweenDateTimeAndNextWeekdayTime(nowDate, nextWeekday.timePeriod.from);
214
+ if (minutesToTomorrowOpen >= 60) {
215
+ return formatClosedUntilWeekday(nextWeekday, T);
216
+ } else {
217
+ return formatOpeningInMinutes(minutesToTomorrowOpen, T);
218
+ }
219
+ } else {
220
+ const nextWorkingWeekday = findNextWorkingWeekday(weekdayPeriods, nowDate);
221
+ return nextWorkingWeekday ? formatClosedUntilWeekday(nextWorkingWeekday, T) : "";
222
+ }
223
+ }
224
+ function prepareTimeToTodayClose(nowDate, currentWeekday, T) {
225
+ const minutesToClose = minutesBetweenDateTimeAndWeekdayTime(nowDate, currentWeekday.timePeriod.to);
226
+ if (minutesToClose >= 60) {
227
+ return formatOpenUntilHours(currentWeekday, T);
228
+ } else {
229
+ return formatClosingInMinutes(minutesToClose, T);
230
+ }
231
+ }
232
+ function prepareTimeToTodayOpen(nowDate, currentWeekday, T) {
233
+ const minutesToOpen = minutesBetweenDateTimeAndWeekdayTime(nowDate, currentWeekday.timePeriod.from);
234
+ if (minutesToOpen >= 60) {
235
+ return formatClosedUntilHours(currentWeekday, T);
236
+ } else {
237
+ return formatOpeningInMinutes(minutesToOpen, T);
238
+ }
239
+ }
240
+ function isDateInWeekdayOpenHours(date, weekday) {
241
+ const { from, to } = weekday.timePeriod;
242
+ return isInTimePeriod(date.getHours(), date.getMinutes(), from.hours, from.minutes, to.hours, to.minutes);
243
+ }
244
+ function getNextDayDate(date) {
245
+ const nextDate = new Date(date);
246
+ nextDate.setDate(nextDate.getDate() + 1);
247
+ return nextDate;
248
+ }
249
+ function compareDateTimeAndWeekdayTime(date, weekdayHours) {
250
+ const minutesBetween = minutesBetweenDateTimeAndWeekdayTime(date, weekdayHours);
251
+ if (minutesBetween === 0) {
252
+ return 0;
253
+ }
254
+ if (minutesBetween > 0) {
255
+ return 1;
256
+ }
257
+ return -1;
258
+ }
259
+ function minutesBetweenDateTimeAndWeekdayTime(dateTime, weekdayTime) {
260
+ const dateTimeMinutes = dateTime.getHours() * 60 + dateTime.getMinutes();
261
+ const weekdayTimeMinutes = weekdayTime.hours * 60 + weekdayTime.minutes;
262
+ return weekdayTimeMinutes - dateTimeMinutes;
263
+ }
264
+ function minutesBetweenDateTimeAndNextWeekdayTime(dateTime, weekdayTime) {
265
+ const dateTimeMinutes = dateTime.getHours() * 60 + dateTime.getMinutes();
266
+ const weekdayTimeMinutes = weekdayTime.hours * 60 + weekdayTime.minutes;
267
+ const midnightMinutes = 24 * 60;
268
+ return weekdayTimeMinutes + (midnightMinutes - dateTimeMinutes);
269
+ }
270
+ const formatOpeningInMinutes = (minutesToOpen, T) => T("ui:Opening in _minutes_", { count: minutesToOpen });
271
+ const formatClosingInMinutes = (minutesToClose, T) => T("ui:Closing in _minutes_", { count: minutesToClose });
272
+ const formatClosedUntilHours = (weekday, T) => {
273
+ const { hours, minutes } = weekday.timePeriod.from;
274
+ const formattedTime = formatTimeAmPm(hours, minutes);
275
+ return T("ui:Closed until _time_", { time: formattedTime });
276
+ };
277
+ const formatOpenUntilHours = (weekday, T) => {
278
+ const { hours, minutes } = weekday.timePeriod.to;
279
+ const formattedTime = formatTimeAmPm(hours, minutes);
280
+ return T("ui:Open until _time_", { time: formattedTime });
281
+ };
282
+ const formatClosedUntilWeekday = (weekday, T) => {
283
+ const { hours, minutes } = weekday.timePeriod.from;
284
+ const formattedTime = `${weekday.weekday} ${formatTimeAmPm(hours, minutes)}`;
285
+ return T("ui:Closed until _time_", { time: formattedTime });
286
+ };
287
+ const findNextWorkingWeekday = (weekdayPeriods, nowDate) => {
288
+ let startIndex = (nowDate.getDay() + 1) % 7;
289
+ while (!findWeekdayByDayIndex(weekdayPeriods, startIndex)) {
290
+ startIndex = (startIndex + 1) % 7;
291
+ }
292
+ return findWeekdayByDayIndex(weekdayPeriods, startIndex);
293
+ };
294
+
295
+ exports.canParseOperationHours = canParseOperationHours;
296
+ exports.getBoundaryMinutes = getBoundaryMinutes;
297
+ exports.getOpenTimeLabel = getOpenTimeLabel;
298
+ exports.isOpen = isOpen;
299
+ exports.parseAndOrderWeekdays = parseAndOrderWeekdays;
300
+ exports.toLocalDate = toLocalDate;
@@ -9,5 +9,12 @@ const FlightLabelStatus = {
9
9
  DEPARTED: 6,
10
10
  UNKNOWN: 7
11
11
  };
12
+ const PoiOpenStatus = {
13
+ OPEN: "open",
14
+ CLOSED: "closed",
15
+ OPENING_SOON: "opening-soon",
16
+ CLOSING_SOON: "closing-soon"
17
+ };
12
18
 
13
19
  exports.FlightLabelStatus = FlightLabelStatus;
20
+ exports.PoiOpenStatus = PoiOpenStatus;
@@ -1 +1 @@
1
- var a="3.3.1033",e={version:a};export{e as default,a as version};
1
+ var a="3.3.1035",e={version:a};export{e as default,a as version};
@@ -0,0 +1 @@
1
+ import{getOpenTimeLabel as t,canParseOperationHours as n,toLocalDate as o,parseAndOrderWeekdays as r,isOpen as e,getBoundaryMinutes as i}from"../../../src/utils/operationHours.js";import{PoiOpenStatus as s}from"../../../utils/constants.js";function u(t,i,s=new Date){if("permanently-closed"===t.state)return!1;const u=t.dynamicData?.["open-closed-status"];if(u){const t=u.expiresAt;if(void 0===t||t>s.getTime())return u.isOpen}if(!i)return;if(!n(t.operationHours))return;const a=o(s,i),c=r(t.operationHours,a);return c&&0!==c.length?e(c,a):void 0}function a(e,a,f,p=new Date){const O=u(e,a,p);if(void 0===O)return;const m=function(t,e,u,a){const f=u?s.OPEN:s.CLOSED;if(!e||!n(t.operationHours))return f;const p=o(a,e),O=r(t.operationHours,p);if(!O||0===O.length)return f;const{minutesToOpen:m,minutesToClose:l}=i(O,p);if(u)return c(l)?s.CLOSING_SOON:s.OPEN;return c(m)?s.OPENING_SOON:s.CLOSED}(e,a,O,p);return{isOpen:O,status:m,timeLabel:a&&t(e.operationHours,p,f,a)||void 0}}function c(t){return void 0!==t&&t>0&&t<=60}export{u as computeIsOpenNow,a as computePoiOpenStatus};
@@ -1 +1 @@
1
- import*as e from"ramda";import o from"zousan";import{buildStructuresLookup as t}from"../../../src/utils/buildStructureLookup.js";import{debugIsTrue as a}from"../../../src/utils/configUtils.js";import{toLang as i}from"../../../src/utils/i18n.js";async function n(i){const n=i.log.sublog("poiDataManager"),u=()=>{i.bus.send("venueData/loadPoiData")};let p=new o;const d=(e,o)=>{const{position:t}=e,a=o.floorIdToStructure(t.floorId);if(!a)return n.error(`No structure found for floorId: ${t.floorId} for POI ${e.poiId}`),{...e};const i=o.floorIdToFloor(t.floorId),r={...t,structureName:e.structureNameOverride||a.name,buildingId:a.id,floorName:e.levelNameOverride||i.name,floorOrdinal:i.ordinal};return{...e,position:r}},l=(e,o)=>{e.roomInfo||(e.roomInfo=[]),e.roomInfo.push(o)},c=e.pipe(e.propOr([],"externalIds"),e.find(e.propEq("roomId","type")),e.prop("id"),e.unless(e.isNil,e.tail));i.bus.on("venueData/poiDataLoaded",async({pois:o,structures:r})=>{if(o=((o,t)=>e.pipe(e.values,e.map(e=>{e.distance=null,e.staticName=e.name,e.isNavigable=void 0===e.isNavigable||!0===e.isNavigable,e.capacity&&l(e,{name:`Seats ${e.capacity.join("-")}`,svgId:"number-of-seats"}),e.category.startsWith("meeting")&&l(e,{name:i.gt()("poiView:Conference Room"),svgId:"conference-room"});const o=c(e);return o&&(e.roomId=o),[e.poiId,d(e,t)]}),e.fromPairs)(o))(o,t(r)),a(i,"pseudoTransPois"))for(const e in o)o[e]=s(o[e],i.i18n().language);o=function(e){const o=[];return Object.values(e).forEach(e=>{try{const t=e.position;t?["buildingId","structureName","floorId","floorName","floorOrdinal","latitude","longitude"].forEach(a=>{null!==t[a]&&void 0!==t[a]||o.push({id:e.poiId,e:`invalid position property: ${a}: ${t[a]}`})}):o.push({poi:e,e:"No position information"})}catch(t){n.error(t),o.push({id:e.poiId,e:t.message})}}),o.length&&(n.warn("badPois:",o),o.forEach(o=>{delete e[o.id]})),e}(o),await async function(e){for(const o of Object.values(e))await I(o);return e}(o),p.resolve(o),i.config.debug&&i.env.isBrowser&&(window._pois=o),i.config.debug&&async function(e){const o=Date.now(),t=[],a=await i.bus.get("wayfinder/_getNavGraph");Object.values(e).forEach(e=>{try{const o=e.position;a.findClosestNode(o.floorId,o.latitude,o.longitude)||t.push({id:e.poiId,e:"No closest Navgraph Node"})}catch(o){n.error(o),t.push({id:e.poiId,e:o.message})}}),t.length&&n.warn("badPois:",t),n(`Total time for navgraph POI check: ${Date.now()-o}ms`)}(o)}),i.bus.on("poi/getById",async({id:e})=>p.then(o=>o[e])),i.bus.on("poi/getByFloorId",async({floorId:o})=>p.then(e.pickBy(e.pathEq(o,["position","floorId"])))),i.bus.on("poi/getByCategoryId",async({categoryId:o})=>p.then(e.pickBy(e=>e.category===o||e.category.startsWith(o+".")))),i.bus.on("poi/getAll",async()=>p);const m=["queue","primaryQueueId"],f=(o,t,a)=>{const i=e.path(["queue","queueType"],t);if(!i)return null;const n=o[i],r=e.path(m,t);return a.filter(e.pathEq(r,m)).filter(e=>e.poiId!==t.poiId).map(o=>{const t=e.path(["queue","queueSubtype"],o),a=g(t)(n);return{poiId:o.poiId,...a}})},g=o=>{return e.pipe(e.find(e.propEq(o,"id")),(t=`No queue found with ID: ${o}`,e=>{if(null!=e)return e;throw Error(t)}),e.pick(["displayText","imageId"]));var t};i.bus.on("poi/addOtherSecurityLanes",({poi:o})=>(async o=>{if(!e.path(m,o))return o;const t=await i.bus.get("venueData/getQueueTypes"),a=await i.bus.get("poi/getByCategoryId",{categoryId:"security"}),n=Object.values(a);return o.queue.otherQueues=f(t,o,n),o})(o));const y=e=>!!e?.startsWith("https:");async function I(t){if(!t)return;const a="undefined"==typeof window?1:window.devicePixelRatio||1,n=`${Math.round(351*a)}x${Math.round(197*a)}`;return e.length(t.images)?y(t.images[0])||(t.images=await o.all(t.images.map(e=>i.bus.get("venueData/getPoiImageUrl",{imageName:e,size:n})))):t.images=[],e.length(t.fullImages)?y(t.fullImages[0]?.url)||(t.fullImages=await o.all(t.fullImages.map(async({url:e,...o})=>({url:await i.bus.get("venueData/getPoiImageUrl",{imageName:e,size:n}),...o})))):t.fullImages=[],t}const h=e.memoizeWith(e.identity,e.pipe(e.pluck("category"),e.values,e.uniq));i.bus.on("poi/getAllCategories",async()=>p.then(h)),i.bus.on("venueData/loadNewVenue",()=>{p=new o,u()}),i.bus.on("poi/setDynamicData",({plugin:o,idValuesMap:t})=>{p.then(a=>{for(const i in t){const n=a[i].dynamicData||{};n[o]={...t[i]};const r=e.mergeRight(a[i],{dynamicData:n});a[i]=r}})}),i.bus.on("poi/setCoreAttributes",e=>{p.then(o=>{const t=[];for(const a in e){r(o,a,e[a]?.name)&&(i.bus.send("map/mutateFeature",{poiId:a,name:o[a].name}),t.push(o[a]))}t.length>0&&i.bus.send("poi/updated",{pois:t})})});return{init:u,runTest:async e=>(await e(),p),internal:{addImages:I,fixPositionInfo:d,pseudoTransPoi:s,applyPoiNameOverride:r}}}function r(e,o,t){return!!e[o]&&(e[o].name=t||e[o].staticName,!0)}function s(e,o){return["description","nearbyLandmark","name","phone","operationHours"].forEach(t=>{e[t]&&(e[t]=i(e[t],o))}),e.keywords&&(e.keywords=e.keywords.map(e=>(e.name=i(e.name,o),e))),e.position.floorName&&(e.position.floorName=i(e.position.floorName,o)),e.position.structureName&&(e.position.structureName=i(e.position.structureName,o)),e}export{r as applyPoiNameOverride,n as create};
1
+ import*as e from"ramda";import o from"zousan";import{buildStructuresLookup as t}from"../../../src/utils/buildStructureLookup.js";import{debugIsTrue as a}from"../../../src/utils/configUtils.js";import{toLang as i}from"../../../src/utils/i18n.js";import{computePoiOpenStatus as n}from"./computeIsOpenNow.js";async function r(i,r){const p=i.log.sublog("poiDataManager"),d=!0===r?.enableOpenStatus,c=()=>{i.bus.send("venueData/loadPoiData")};let l=new o;const m=(e,o)=>{const{position:t}=e,a=o.floorIdToStructure(t.floorId);if(!a)return p.error(`No structure found for floorId: ${t.floorId} for POI ${e.poiId}`),{...e};const i=o.floorIdToFloor(t.floorId),n={...t,structureName:e.structureNameOverride||a.name,buildingId:a.id,floorName:e.levelNameOverride||i.name,floorOrdinal:i.ordinal};return{...e,position:n}},f=(e,o)=>{e.roomInfo||(e.roomInfo=[]),e.roomInfo.push(o)},g=e.pipe(e.propOr([],"externalIds"),e.find(e.propEq("roomId","type")),e.prop("id"),e.unless(e.isNil,e.tail));i.bus.on("venueData/poiDataLoaded",async({pois:o,structures:n})=>{if(o=((o,t)=>e.pipe(e.values,e.map(e=>{e.distance=null,e.staticName=e.name,e.isNavigable=void 0===e.isNavigable||!0===e.isNavigable,e.capacity&&f(e,{name:`Seats ${e.capacity.join("-")}`,svgId:"number-of-seats"}),e.category.startsWith("meeting")&&f(e,{name:i.gt()("poiView:Conference Room"),svgId:"conference-room"});const o=g(e);return o&&(e.roomId=o),[e.poiId,m(e,t)]}),e.fromPairs)(o))(o,t(n)),a(i,"pseudoTransPois"))for(const e in o)o[e]=u(o[e],i.i18n().language);o=function(e){const o=[];return Object.values(e).forEach(e=>{try{const t=e.position;t?["buildingId","structureName","floorId","floorName","floorOrdinal","latitude","longitude"].forEach(a=>{null!==t[a]&&void 0!==t[a]||o.push({id:e.poiId,e:`invalid position property: ${a}: ${t[a]}`})}):o.push({poi:e,e:"No position information"})}catch(t){p.error(t),o.push({id:e.poiId,e:t.message})}}),o.length&&(p.warn("badPois:",o),o.forEach(o=>{delete e[o.id]})),e}(o),await async function(e){for(const o of Object.values(e))await w(o);return e}(o),l.resolve(o),i.config.debug&&i.env.isBrowser&&(window._pois=o),i.config.debug&&async function(e){const o=Date.now(),t=[],a=await i.bus.get("wayfinder/_getNavGraph");Object.values(e).forEach(e=>{try{const o=e.position;a.findClosestNode(o.floorId,o.latitude,o.longitude)||t.push({id:e.poiId,e:"No closest Navgraph Node"})}catch(o){p.error(o),t.push({id:e.poiId,e:o.message})}}),t.length&&p.warn("badPois:",t),p(`Total time for navgraph POI check: ${Date.now()-o}ms`)}(o)}),i.bus.on("poi/getById",async({id:e})=>l.then(o=>o[e])),i.bus.on("poi/getByFloorId",async({floorId:o})=>l.then(e.pickBy(e.pathEq(o,["position","floorId"])))),i.bus.on("poi/getByCategoryId",async({categoryId:o})=>l.then(e.pickBy(e=>e.category===o||e.category.startsWith(o+".")))),i.bus.on("poi/getAll",async()=>l),i.bus.on("poi/getOpenStatus",async({id:e,now:o})=>{if(!d)return;const t=(await l)[e];if(!t)return;const a=await i.bus.get("venueData/getVenueTimezone");return n(t,a,i.gt(),o??new Date)});const y=["queue","primaryQueueId"],I=(o,t,a)=>{const i=e.path(["queue","queueType"],t);if(!i)return null;const n=o[i],r=e.path(y,t);return a.filter(e.pathEq(r,y)).filter(e=>e.poiId!==t.poiId).map(o=>{const t=e.path(["queue","queueSubtype"],o),a=h(t)(n);return{poiId:o.poiId,...a}})},h=o=>{return e.pipe(e.find(e.propEq(o,"id")),(t=`No queue found with ID: ${o}`,e=>{if(null!=e)return e;throw Error(t)}),e.pick(["displayText","imageId"]));var t};i.bus.on("poi/addOtherSecurityLanes",({poi:o})=>(async o=>{if(!e.path(y,o))return o;const t=await i.bus.get("venueData/getQueueTypes"),a=await i.bus.get("poi/getByCategoryId",{categoryId:"security"}),n=Object.values(a);return o.queue.otherQueues=I(t,o,n),o})(o));const b=e=>!!e?.startsWith("https:");async function w(t){if(!t)return;const a="undefined"==typeof window?1:window.devicePixelRatio||1,n=`${Math.round(351*a)}x${Math.round(197*a)}`;return e.length(t.images)?b(t.images[0])||(t.images=await o.all(t.images.map(e=>i.bus.get("venueData/getPoiImageUrl",{imageName:e,size:n})))):t.images=[],e.length(t.fullImages)?b(t.fullImages[0]?.url)||(t.fullImages=await o.all(t.fullImages.map(async({url:e,...o})=>({url:await i.bus.get("venueData/getPoiImageUrl",{imageName:e,size:n}),...o})))):t.fullImages=[],t}const v=e.memoizeWith(e.identity,e.pipe(e.pluck("category"),e.values,e.uniq));i.bus.on("poi/getAllCategories",async()=>l.then(v)),i.bus.on("venueData/loadNewVenue",()=>{l=new o,c()}),i.bus.on("poi/setDynamicData",async({plugin:o,idValuesMap:t})=>{const a=await l;for(const i in t){const n=a[i].dynamicData||{};n[o]={...t[i]};const r=e.mergeRight(a[i],{dynamicData:n});a[i]=r}}),i.bus.on("poi/setCoreAttributes",e=>{l.then(o=>{const t=[];for(const a in e){s(o,a,e[a]?.name)&&(i.bus.send("map/mutateFeature",{poiId:a,name:o[a].name}),t.push(o[a]))}t.length>0&&i.bus.send("poi/updated",{pois:t})})});return{init:c,runTest:async e=>(await e(),l),internal:{addImages:w,fixPositionInfo:m,pseudoTransPoi:u,applyPoiNameOverride:s}}}function s(e,o,t){return!!e[o]&&(e[o].name=t||e[o].staticName,!0)}function u(e,o){return["description","nearbyLandmark","name","phone","operationHours"].forEach(t=>{e[t]&&(e[t]=i(e[t],o))}),e.keywords&&(e.keywords=e.keywords.map(e=>(e.name=i(e.name,o),e))),e.position.floorName&&(e.position.floorName=i(e.position.floorName,o)),e.position.structureName&&(e.position.structureName=i(e.position.structureName,o)),e}export{s as applyPoiNameOverride,r as create};
@@ -0,0 +1 @@
1
+ import{DateTime as t}from"luxon";import*as n from"ramda";function e(t){if(!t||"string"!=typeof t)return!1;const n=t.trim();if(""===n)return!1;const e=/^(Su|Mo|Tu|We|Th|Fr|Sa)(-(?:Su|Mo|Tu|We|Th|Fr|Sa))?\s+\d{1,2}:\d{2}-\d{1,2}:\d{2}$/;return n.split(";").map(t=>t.trim()).every(t=>e.test(t))}function r(t,n){const e=s(t,n);if(!e)return!1;const r=n.getHours(),o=n.getMinutes(),{from:i,to:c}=e.timePeriod;return u(r,o,i.hours,i.minutes,c.hours,c.minutes)}function o(t,n){const e=s(t,n);return e?{minutesToOpen:D(n,e.timePeriod.from),minutesToClose:D(n,e.timePeriod.to)}:{minutesToOpen:void 0,minutesToClose:void 0}}function u(t,n,e,r,o,s){if(i(e,r,o,s))return u(t,n,e,r,24,0)||u(t,n,0,0,o,s);{const u=i(t,n,e,r),c=i(o,s,t,n);return u&&c}}function i(t,n,e,r){return t>e||t===e&&n>=r}function s(t,n){return c(t,n.getDay())}function c(t,n){const e=a[n];return t.find(({weekday:t})=>t===e)}function m(t,e){const r=function(t){return t.split(l).map(t=>t.trim()).map(t=>t.split(p)).flatMap(([t,n])=>{const e=function(t){const[n,e]=t.split(y),r=f[n];let o;if(e){o=function(t,n){const e=[t];let r=t;do{r=(r+1)%a.length,e.push(r)}while(r!==n);return e}(r,f[e])}else o=[r];return o.map(t=>a[t])}(t),r=function(t){const[n,e]=t.split(h),[r,o]=M(n),[u,i]=M(e);return{from:r,to:u,formatted:o+` ${h} `+i}}(n);return function(t,n){return t.map(t=>({weekday:t,timePeriod:n}))}(e,r)})}(t),o=function(t){const n=0,e=[];return t.forEach(t=>{let r=d[t.weekday]-n;r<0&&(r+=a.length),e[r]=t}),function(t){return t.filter(t=>Boolean(t))}(e)}(r);return function(t,e){const r=a[e.getDay()],o=n.converge(n.assoc("isToday"),[n.propEq(r,"weekday"),n.identity]);return t.map(t=>o(t))}(o,e)}const f={Su:0,Mo:1,Tu:2,We:3,Th:4,Fr:5,Sa:6},a=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],d=a.reduce((t,n,e)=>Object.assign(t,{[n]:e}),{}),l=";",p=/\s+/,y="-",h="-",g=":",P=" AM",T=" PM";function M(t){const[n,e]=t.split(g);return[{hours:+n,minutes:+e},S(n,e)]}function S(t,n){const e=+t,r=+n,o=e<12||24===e?P:T,u=e%12||12,i=r>9?String(r):"0"+r;return u+g+i+o}function _(t,n,r,o){if("Mo-Su 00:00-24:00"===t)return r("ui:Always open");if(!t)return"";if(!e(t))return"";const i=w(n,o),c=m(t,i);if(!c)return"";const f=s(c,i);return f&&-1!==function(t,n){const e=D(t,n);if(0===e)return 0;if(e>0)return 1;return-1}(i,f.timePeriod.to)?function(t,n){const{from:e,to:r}=n.timePeriod;return u(t.getHours(),t.getMinutes(),e.hours,e.minutes,r.hours,r.minutes)}(i,f)?function(t,n,e){const r=D(t,n.timePeriod.to);return r>=60?O(n,e):v(r,e)}(i,f,r):function(t,n,e){const r=D(t,n.timePeriod.from);return r>=60?C(n,e):k(r,e)}(i,f,r):function(t,n,e){const r=function(t){const n=new Date(t);return n.setDate(n.getDate()+1),n}(t),o=s(n,r);if(o){const n=function(t,n){const e=60*t.getHours()+t.getMinutes(),r=60*n.hours+n.minutes;return r+(1440-e)}(t,o.timePeriod.from);return n>=60?F(o,e):k(n,e)}{const r=H(n,t);return r?F(r,e):""}}(i,c,r)}function w(n,e){const{year:r,month:o,day:u,hour:i,minute:s}=t.fromJSDate(n,{zone:e??void 0});return new Date(r,o-1,u,i,s)}function D(t,n){const e=60*t.getHours()+t.getMinutes();return 60*n.hours+n.minutes-e}const k=(t,n)=>n("ui:Opening in _minutes_",{count:t}),v=(t,n)=>n("ui:Closing in _minutes_",{count:t}),C=(t,n)=>{const{hours:e,minutes:r}=t.timePeriod.from;return n("ui:Closed until _time_",{time:S(e,r)})},O=(t,n)=>{const{hours:e,minutes:r}=t.timePeriod.to;return n("ui:Open until _time_",{time:S(e,r)})},F=(t,n)=>{const{hours:e,minutes:r}=t.timePeriod.from;return n("ui:Closed until _time_",{time:`${t.weekday} ${S(e,r)}`})},H=(t,n)=>{let e=(n.getDay()+1)%7;for(;!c(t,e);)e=(e+1)%7;return c(t,e)};export{e as canParseOperationHours,o as getBoundaryMinutes,_ as getOpenTimeLabel,r as isOpen,m as parseAndOrderWeekdays,w as toLocalDate};
@@ -1 +1 @@
1
- const E={ON_TIME:1,EARLY:2,DELAYED:3,CANCELLED:4,ARRIVED:5,DEPARTED:6,UNKNOWN:7};export{E as FlightLabelStatus};
1
+ const E={ON_TIME:1,EARLY:2,DELAYED:3,CANCELLED:4,ARRIVED:5,DEPARTED:6,UNKNOWN:7},N={OPEN:"open",CLOSED:"closed",OPENING_SOON:"opening-soon",CLOSING_SOON:"closing-soon"};export{E as FlightLabelStatus,N as PoiOpenStatus};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atriusmaps-node-sdk",
3
- "version": "3.3.1033",
3
+ "version": "3.3.1035",
4
4
  "description": "This project provides an API to Atrius Personal Wayfinder maps within a Node environment. See the README.md for more information",
5
5
  "keywords": [
6
6
  "acuitybrands",