forest-express
Version: 
Official package for all Forest Express Lianas
129 lines (124 loc) • 5.85 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _ = require('lodash');
var logger = require('./logger');
var Schemas = require('../generators/schemas');
var DEPTH_MAX_FOR_INJECTION = 0;
function SmartFieldsValuesInjector(record, modelName, fieldsPerModel) {
  var depth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
  var requestedField = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
  var schema = Schemas.schemas[modelName];
  var fieldsForHighlightedSearch = [];
  this.getFieldsForHighlightedSearch = function () {
    return fieldsForHighlightedSearch;
  };
  // NOTICE: Field reference format: `modelName.property`.
  function getReferencedModelName(field) {
    return field.reference.split('.')[0];
  }
  // eslint-disable-next-line
  function setSmartFieldValue(record, field, modelName) {
    if (field.value) {
      logger.warn("DEPRECATION WARNING: Smart Fields \"value\" method is deprecated. Please use \"get\" method in your collection ".concat(modelName, " instead."));
    }
    var value;
    try {
      value = field.get ? field.get(record) : field.value(record);
    } catch (error) {
      logger.error("Cannot retrieve the ".concat(field.field, " value because of an internal error in the getter implementation: "), error);
    }
    if (!_.isNil(value)) {
      if (!_.isFunction(value.then)) {
        value = Promise.resolve(value);
      }
      return value.then( /*#__PURE__*/function () {
        var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(smartFieldValue) {
          var smartFieldsValuesInjector;
          return _regenerator["default"].wrap(function _callee$(_context) {
            while (1) switch (_context.prev = _context.next) {
              case 0:
                if (!(depth <= DEPTH_MAX_FOR_INJECTION && smartFieldValue && field.reference)) {
                  _context.next = 4;
                  break;
                }
                smartFieldsValuesInjector = new SmartFieldsValuesInjector(smartFieldValue, getReferencedModelName(field), fieldsPerModel, depth + 1, field.field);
                _context.next = 4;
                return smartFieldsValuesInjector.perform();
              case 4:
                // NOTICE: Sequelize magic accessors can be overriden here
                // but it is not an issue as they are not used in the process of adding
                // smart fields
                record[field.field] = smartFieldValue;
                // NOTICE: String fields can be highlighted.
                if (field.type === 'String') {
                  fieldsForHighlightedSearch.push(field.field);
                }
              case 6:
              case "end":
                return _context.stop();
            }
          }, _callee);
        }));
        return function (_x) {
          return _ref.apply(this, arguments);
        };
      }())["catch"](function (error) {
        logger.warn("Cannot set the ".concat(field.field, " value because of an unexpected error: "), error);
      });
    }
  }
  function isRequestedField(modelNameToCheck, fieldName) {
    return fieldsPerModel && fieldsPerModel[modelNameToCheck] && fieldsPerModel[modelNameToCheck].indexOf(fieldName) !== -1;
  }
  // eslint-disable-next-line sonarjs/cognitive-complexity
  function injectSmartFieldValue(field) {
    var fieldWasRequested = isRequestedField(requestedField || modelName, field.field);
    if (record && field.isVirtual && (field.get || field.value)) {
      if (fieldsPerModel && !fieldWasRequested) {
        return null;
      }
      return setSmartFieldValue(record, field, modelName);
    }
    if (!record[field.field] && _.isArray(field.type) && (field.relationship || field.isVirtual)) {
      // Add empty arrays on relation fields so that JsonApiSerializer add the relevant
      // `data.x.relationships` section in the response.
      //
      // The field must match the following condition
      // - field is a real or a smart HasMany / BelongsToMany relation
      // - field is NOT an 'embedded' relationship (@see mongoose)
      record[field.field] = [];
    } else if (field.reference && !_.isArray(field.type)) {
      // NOTICE: Set Smart Fields values to "belongsTo" associated records.
      var modelNameAssociation = getReferencedModelName(field);
      var schemaAssociation = Schemas.schemas[modelNameAssociation];
      if (schemaAssociation && !_.isArray(field.type)) {
        return Promise.all(schemaAssociation.fields.map(function (fieldAssociation) {
          if (record && record[field.field] && fieldAssociation.isVirtual && (fieldAssociation.get || fieldAssociation.value)) {
            if (fieldsPerModel && !isRequestedField(field.field, fieldAssociation.field)) {
              return null;
            }
            return setSmartFieldValue(record[field.field], fieldAssociation, modelNameAssociation);
          }
          return null;
        }));
      }
    }
    return null;
  }
  this.perform = /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() {
    return _regenerator["default"].wrap(function _callee2$(_context2) {
      while (1) switch (_context2.prev = _context2.next) {
        case 0:
          return _context2.abrupt("return", Promise.all(schema.fields.map(function (field) {
            return injectSmartFieldValue(field);
          })));
        case 1:
        case "end":
          return _context2.stop();
      }
    }, _callee2);
  }));
}
module.exports = SmartFieldsValuesInjector;