UNPKG

ednl-liftstatus-web-components

Version:
121 lines (120 loc) 5.01 kB
import { createStore } from "@stencil/store"; import dayjs from "dayjs"; import { isEmpty } from "lodash-es"; import PubSub from "pubsub-js"; const ID_KEY_PREFIX = "ednl-ls-"; const DATA_TOPIC_POSTFIX = "-data"; const SUBS_TOPIC_POSTFIX = "-subs"; const storesContainer = createStore({ updatedAt: Date.now(), stores: new Map(), }); export function createNewStore(idKey, initialState) { // Gather initial state, use defaults if not provided const newStore = createStore({ historicalSensorData: (initialState === null || initialState === void 0 ? void 0 : initialState.historicalSensorData) || [], currentSensorData: (initialState === null || initialState === void 0 ? void 0 : initialState.currentSensorData) || { lastUpdate: 0, values: {}, updated: {}, }, datePicker: (initialState === null || initialState === void 0 ? void 0 : initialState.datePicker) || { start: dayjs() .hour(dayjs().hour()) .minute(0) .second(0) .millisecond(0) .toISOString(), end: dayjs() .hour(dayjs().hour() + 1) .minute(0) .second(0) .millisecond(0) .toISOString(), // End date/time in ISO 8601 string }, error: (initialState === null || initialState === void 0 ? void 0 : initialState.error) || { message: "", type: "", }, hasBackDoor: (initialState === null || initialState === void 0 ? void 0 : initialState.hasBackDoor) || false, }); // Create new store storesContainer.state.stores.set(ID_KEY_PREFIX + idKey, newStore); // Update updatedAt to notify subscribers storesContainer.set("updatedAt", Date.now()); // Listen for new subscriptions and react by publishing the current state PubSub.subscribe(ID_KEY_PREFIX + idKey + SUBS_TOPIC_POSTFIX, () => { publishData(idKey); }); // Publish the data for existing subscribers publishData(idKey); } export async function getStore(idKey) { const idKeyWithPrefix = ID_KEY_PREFIX + idKey; // We need to return a promise for stencil lifecycle methods to be able to await // See: https://stenciljs.com/docs/component-lifecycle#async-lifecycle-methods return new Promise((resolve, reject) => { // If no idKey is provided, return first store, but only if there is only one store in the container // We do this to allow backwards compatibility with the old way of using the web components (where there was only one installation) // Multiple stores and no idKey indicates user error if (isEmpty(idKey) && storesContainer.state.stores.size > 1) { reject("Add the idKey to the <ls-data> component like so: <ls-data id-key='yourUniqueKey'></ls-data>"); } // If no idKey is provided, return first store if (isEmpty(idKey) && !isEmpty(storesContainer.state.stores.values().next().value)) { resolve(storesContainer.state.stores.values().next().value); } // If store exists, return it if (!isEmpty(idKey) && !isEmpty(storesContainer.state.stores.get(idKeyWithPrefix))) { resolve(storesContainer.state.stores.get(idKeyWithPrefix)); } // If store doesn't exist, wait for it to be created storesContainer.onChange("updatedAt", () => { // Multiple stores and no idKey indicates user error if (isEmpty(idKey) && storesContainer.state.stores.size > 1) { reject("Add the idKey to the <ls-data> component like so: <ls-data id-key='yourUniqueKey'></ls-data>"); } // If no idKey is provided, return first store if (isEmpty(idKey) && !isEmpty(storesContainer.state.stores.values().next().value)) { resolve(storesContainer.state.stores.values().next().value); } // If store exists, return it if (!isEmpty(idKey) && !isEmpty(storesContainer.state.stores.get(idKeyWithPrefix))) { resolve(storesContainer.state.stores.get(idKeyWithPrefix)); } }); }); } export async function updateStore(currentSensorData, idKey) { const store = await getStore(idKey); // Update sensor data store.set("currentSensorData", currentSensorData); // Update updatedAt to notify subscribers storesContainer.set("updatedAt", Date.now()); // Publish data for external use publishData(idKey); } /** * This method publishes current state op the store to the data topic. * This is used for external applications to subscribe to. Customers can install PubSubJS and subscribe to the data topic. * Other components use the store directly. */ async function publishData(idKey) { const dataTopic = ID_KEY_PREFIX + idKey + DATA_TOPIC_POSTFIX; const subscriptionCount = PubSub.countSubscriptions(dataTopic); const store = await getStore(idKey); const state = { currentSensorData: store.state.currentSensorData, error: store.state.error, hasBackDoor: store.state.hasBackDoor, }; // Publish the data for existing subscribers if (subscriptionCount > 0) { PubSub.publish(dataTopic, state); } } //# sourceMappingURL=store.js.map