All files / datastore index.js

95.23% Statements 20/21
78.57% Branches 11/14
100% Functions 7/7
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77                                                      5x     5x 3x   2x         8x   12x 12x 12x 1x   12x     6x 1x     5x 5x         5x 5x   5x     1x     4x         7x        
import * as R from 'ramda';
 
/**
 * Simple reactive vannillajs data store
 *
 * NOTES
 * - accepts an event emitter which handles reactivity mechanism, for example could use:
 *   - emit CustomEvent
 *   - pubsub model
 * - requires work to support back to IE
 *   - ownKeys trap in Proxy (ownKeys is not in IE polyfill for Proxy)
 * @namespace datastore
 * @memberof thirstieclient
 */
/**
 * Define a data store
 * @constructor thirstieDataStore
 * @param {Object} data
 * @param {Function} emitter
 * @returns {Proxy}
 */
function thirstieDataStore (data = {}, emitter = null) {
  /**
   * Publish updates (by emitting events)
   * @param  {*}      eventDetail Any details to pass along with the event
   */
  function onChange (changeDetail, newState) {
    const eventDetail = {
      changeDetail, newState
    };
    if (emitter) {
      return emitter(eventDetail);
    } else {
      return false;
    }
  }
 
  function handler (data) {
    return {
      get (obj, prop) {
        Iif (prop === '_isProxy') return true;
        const objType = Object.prototype.toString.call(obj[prop]).slice(8, -1).toLowerCase();
        if ([ 'object', 'array' ].includes(objType) && !obj[prop]._isProxy) {
          obj[prop] = new Proxy(obj[prop], handler(data));
        }
        return obj[prop];
      },
      set (obj, prop, value) {
        if (!Object.hasOwn(obj, prop)) {
          throw new Error(`Access denied: ${prop} ${value}`);
        }
        // set value and call onChange only if we are changing the value
        Eif (!R.equals(obj[prop], value)) {
          const changeDetail = {
            prop,
            oldValue: obj[prop],
            newValue: value
          };
          obj[prop] = value;
          onChange(changeDetail, obj);
        }
        return true;
      },
      deleteProperty (obj, prop) {
        return false;
      },
      ownKeys (obj) {
        return Reflect.ownKeys(obj);
      }
    };
  };
 
  return new Proxy(data, handler(data));
}
 
export default thirstieDataStore;