ecosystem-webdata.js

// used to append interfaces to omnicore sdk so that created app and AppStudio can use
import API from './ecosystem-base.js';
import {Logger} from './../function/log-helper.js';
import {InfoType, WarningType} from '../information/informationCode.js';
import {ErrorCode} from '../exception/exceptionDesc.js';
import Store from '../store/store.js';
import {Webdata} from '../store/const.js';

const factoryApiWebdataMonitor = function (es) {
  const logModule = 'ecosystem-webdata';

  /**
   * The API.WEBDATAMONITOR namespace provides a set of interfaces for easily and quickly adding webdata monitoring and processing transactions.
   * The webdata variable can be added under the container component (behavior --> Add variable), and the variable can be used in the code editor.
   * This API allows you to monitor changes to webdata variables and update their values.
   * This API is ideal for situations where you want stateful management, but don't want to use RAPID variables.
   * @alias API.WEBDATAMONITOR
   * @namespace
   *
   */
  es.WEBDATAMONITOR = new (function () {
    this.STATE = {};
    this.$on = [];

    this.createResourceName = function (key) {
      const name = Store.generateMappingKey(Webdata, [key]);
      this.$on.push(name);
      this.$on = [...new Set(this.$on)];
      return name;
    };

    this.splitKey = function (key = 'App.a') {
      // Logger.i(logModule, `splitKey: ${key}`);
      return key
        .split('.')
        .map((k) => `['${k}']`)
        .join('');
    };

    this.initState = function (state) {
      Object.assign(this.STATE, state);
    };

    /**
     * Unsubscribes from the variable state
     *
     */
    this.unsubscribeAll = function () {
      this.$on.forEach((name) => {
        es._events.off(name);
      });
      this.$on = [];
    };

    /**
     * Subscribes to a webdata.
     * @alias monitorWebdata
     * @memberof API.WEBDATAMONITOR
     * @param {string} [key] The webdata name.
     * @param {function} [callback] The callback function that is called when the webdata changes.
     *
     * @example
     * API.WEBDATAMONITOR.monitorWebdata(
     *  "App.page.LayoutInfo_1.mode",
     *  (v)=>{
     *    console.log(v);
     *  }
     * )
     */
    this.monitorWebdata = async function (key = 'App.a', callback = null) {
      Logger.i(InfoType.WebdataOperation, `Trying to monitor a webdata with key ${key}`);
      //read the state the first time
      if (typeof callback === 'function') {
        const keys = this.splitKey(key);
        try {
          const value = eval(`this.STATE${keys}`);
          callback(value);
        } catch (error) {
          return API.rejectWithStatus(`Get webdata ${key} failed`, error, {errorCode: ErrorCode.FailedToGetWebdata});
        }
      }

      if (es.isSubscriptionBlocked) {
        Logger.w(
          WarningType.RWSSubscriptionBlocked,
          `API.Webdata: Subscription disabled when trying to monitor webdata ${key}`,
        );
        return;
      }

      es._events.on(this.createResourceName(key), callback);
    };

    /**
     * Updates the value of a specified webdata.
     * @alias setWebdata
     * @memberof API.WEBDATAMONITOR
     * @param {string} [key] The webdata name.
     * @param {string} [value] The value to be updated.
     *
     * @example
     * API.WEBDATAMONITOR.setWebdata(
     *  "App.page.LayoutInfo_1.mode",
     *   "manual"
     * )
     *
     */
    this.setWebdata = function (key = 'App.a', value) {
      //Reminder:the variable user got from codeEditor is "Webdata.App.a"
      const filterKey = key.replace('Webdata.', '');
      const keyParts = filterKey.split('.');

      let obj = this.STATE;
      for (let i = 0; i < keyParts.length - 1; i++) {
        if (!Object.prototype.hasOwnProperty.call(obj, keyParts[i])) {
          obj[keyParts[i]] = {};
        }
        obj = obj[keyParts[i]];
      }
      obj[keyParts[keyParts.length - 1]] = value;

      es._events.trigger(this.createResourceName(filterKey), value);
    };

    /**
     * Gset the webdata's value.
     * @alias getWebdata
     * @memberof API.WEBDATAMONITOR
     * @param {string} [key] The key name of the webdata.
     * @returns {Promise<object>} The webdata value.
     *
     * @example
     * const webdataMode = API.WEBDATAMONITOR.getWebdata("App.page.LayoutInfo_1.mode");
     * console.log(webdataMode)
     *
     */
    this.getWebdata = function (key = 'App.a') {
      const keys = this.splitKey(key);
      try {
        return eval(`this.STATE${keys}`);
      } catch (error) {
        return API.rejectWithStatus(`Get webdata ${key} failed`, error, {errorCode: ErrorCode.FailedToGetWebdata});
      }
    };
  })();

  es.constructedWebdataMonitor = true;
};

if (typeof API.constructedWebdataMonitor === 'undefined') {
  factoryApiWebdataMonitor(API);
}

export default API;
export {factoryApiWebdataMonitor};