UNPKG

atriusmaps-node-sdk

Version:

This project provides an API to Atrius Personal Wayfinder maps within a Node environment. See the README.md for more information

150 lines (146 loc) 5.5 kB
'use strict'; var Zousan = require('zousan'); var processors = require('./processors.js'); let REFRESH_FREQUENCY = 1e3 * 30; const MARKETPLACE_URL_BASE = "https://marketplace.locuslabs.com"; const MAX_FETCH_FAILS = 3; const ACCOUNT_ID_HEADER = "x-account-id"; const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value); function create(app, config = {}) { const state = { dynamicDataNotPending: new Zousan() }; const T = app.gt(); const getSecurityWaitTimes = async ({ isOpen } = {}) => { const pois = await app.bus.get("poi/getAll"); return Object.values(pois).filter( (poi) => poi.category === "security.checkpoint" && poi?.dynamicData?.security && isObject(poi?.dynamicData?.security) && (isOpen === void 0 ? true : poi?.dynamicData?.security?.isTemporarilyClosed !== isOpen) ).map((poi) => ({ id: poi.poiId, name: poi.name, ...poi.dynamicData.security })); }; if (config._overrideRefreshFrequency) { REFRESH_FREQUENCY = config._overrideRefreshFrequency; } const previousNameOverrides = /* @__PURE__ */ new Map(); app.bus.on("system/readywhenyouare", () => state.dynamicDataNotPending); app.bus.on("dynamicPois/getSecurityWaitTimes", getSecurityWaitTimes); const init = async () => { const [accountId, venueId] = await Promise.all([ app.bus.get("venueData/getAccountId"), app.bus.get("venueData/getVenueId") ]); const dynamicPoisUrl = `${MARKETPLACE_URL_BASE}/venueId/${venueId}/dynamic-poi`; let fetchFailuresCount = 0; let fetchSuccessCount = 0; let fetchIntervalHandle; const updateFromAPI = async () => { const response = await fetch(dynamicPoisUrl, { headers: { [ACCOUNT_ID_HEADER]: accountId } }); if (response.ok) { return response.json().then(({ data }) => processDynamicPois(data)).then(() => { fetchSuccessCount++; }).catch(console.error); } else { console.warn("dynamicPois: fetch response status not ok", response); fetchFailuresCount++; if (fetchFailuresCount >= MAX_FETCH_FAILS && fetchFailuresCount > fetchSuccessCount) { clearInterval(fetchIntervalHandle); } } }; await updateFromAPI().then(() => { fetchIntervalHandle = setInterval(updateFromAPI, REFRESH_FREQUENCY); if (typeof fetchIntervalHandle.unref === "function") { fetchIntervalHandle.unref(); } }).finally(() => state.dynamicDataNotPending.resolve(true)); return () => clearInterval(fetchIntervalHandle); }; async function processDynamicPois(pois) { processParkingPOIS(pois); processOpenClosedPois(pois); processSecurityWaitTimes(pois); processDynamicRouting(pois); processDynamicAttributes(pois); } async function processDynamicAttributes(poiDataMap) { const updates = {}; for (const [poiId, poiData] of Object.entries(poiDataMap)) { const name = poiData?.dynamicData?.poiAttributes?.name ?? null; const previous = previousNameOverrides.get(poiId); if (previous === void 0) { if (name !== null) { updates[poiId] = { name }; previousNameOverrides.set(poiId, name); } } else if (previous !== name) { updates[poiId] = { name }; previousNameOverrides.set(poiId, name); } } for (const [poiId, prevName] of previousNameOverrides.entries()) { if (!(poiId in poiDataMap) && prevName !== null) { updates[poiId] = { name: null }; previousNameOverrides.set(poiId, null); } } if (Object.keys(updates).length > 0) { app.bus.send("poi/setCoreAttributes", updates); const originalNames = await getPoiOriginalNames(Object.keys(updates)); app.bus.send("map/mutateFeature", { functor: processors.mutatePoiName(T, updates, originalNames) }); } } function processParkingPOIS(poiMap) { const idValuesMap = processors.processParkingPOIS(poiMap); app.bus.send("poi/setDynamicData", { plugin: "parking", idValuesMap }); } const getPOILabels = async (idArray) => { const nameMap = {}; for (const poiId of idArray) { const poi = await app.bus.get("poi/getById", { id: poiId }); if (poi) { nameMap[poiId] = poi.name; } } return nameMap; }; const getPoiOriginalNames = async (idArray) => { const nameMap = {}; for (const poiId of idArray) { const poi = await app.bus.get("poi/getById", { id: poiId }); if (poi) { nameMap[poiId] = poi.staticName ?? poi.name; } } return nameMap; }; async function processSecurityWaitTimes(poiMap) { const idValuesMap = processors.processSecurityWaitTimes(poiMap); app.bus.send("poi/setDynamicData", { plugin: "security", idValuesMap }); const labels = await getPOILabels(Object.keys(idValuesMap)); app.bus.send("map/mutateFeature", { functor: processors.mutateSecurityCheckpointLabel(T, idValuesMap, labels) }); } function processOpenClosedPois(poiMap) { const idValuesMap = processors.processOpenClosedPois(poiMap); app.bus.send("poi/setDynamicData", { plugin: "open-closed-status", idValuesMap }); } async function processDynamicRouting(poiMap) { const idValuesMap = await processors.processRoutingPois(poiMap); app.bus.send("poi/setDynamicRouting", { plugin: "routing", idValuesMap }); } return { init }; } exports.create = create;