text: 'use strict';
  
  var _defineProperty = require('babel-runtime/helpers/define-property')['default'];
  
  var _Object$keys = require('babel-runtime/core-js/object/keys')['default'];
  
  var _getIterator = require('babel-runtime/core-js/get-iterator')['default'];
  
  var _Promise = require('babel-runtime/core-js/promise')['default'];
  
  var _Set = require('babel-runtime/core-js/set')['default'];
  
  var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
  
  var _interopRequireWildcard = require('babel-runtime/helpers/interop-require-wildcard')['default'];
  
  Object.defineProperty(exports, '__esModule', {
    value: true
  });
  
  var _validate_records = require('./validate_records');
  
  var _validate_records2 = _interopRequireDefault(_validate_records);
  
  var _check_links = require('./check_links');
  
  var _check_links2 = _interopRequireDefault(_check_links);
  
  var _record_typeEnforce = require('../record_type/enforce');
  
  var _record_typeEnforce2 = _interopRequireDefault(_record_typeEnforce);
  
  var _commonChange = require('../common/change');
  
  var _commonChange2 = _interopRequireDefault(_commonChange);
  
  var _commonMethods = require('../common/methods');
  
  var _commonKeys = require('../common/keys');
  
  var _commonErrors = require('../common/errors');
  
  var _update_helpers = require('./update_helpers');
  
  var updateHelpers = _interopRequireWildcard(_update_helpers);
  
  /**
   * Extend context so that it includes the parsed records and create them.
   * This mutates the response object.
   *
   * @return {Promise}
   */
  
  exports['default'] = function (context) {
    var _this = this;
  
    var adapter = this.adapter;
    var serializer = this.serializer;
    var recordTypes = this.recordTypes;
    var transforms = this.transforms;
  
    var updates = {};
  
    var transaction = undefined;
    var records = undefined;
    var type = undefined;
    var meta = undefined;
    var transform = undefined;
    var fields = undefined;
    var links = undefined;
  
    return serializer.parseCreate(context).then(function (results) {
      records = results;
  
      if (!records || !records.length) throw new _commonErrors.BadRequestError('There are no valid records in the request.');var _context$request = context.request;
      type = _context$request.type;
      meta = _context$request.meta;
  
      transform = transforms[type];
      fields = recordTypes[type];
      links = _Object$keys(fields).filter(function (field) {
        return fields[field][_commonKeys.link];
      });
  
      // Delete denormalized inverse fields.
      for (var field in fields) {
        if (fields[field][_commonKeys.denormalizedInverse]) {
          var _iteratorNormalCompletion = true;
          var _didIteratorError = false;
          var _iteratorError = undefined;
  
          try {
            for (var _iterator = _getIterator(records), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
              var record = _step.value;
  
              delete record[field];
            }
          } catch (err) {
            _didIteratorError = true;
            _iteratorError = err;
          } finally {
            try {
              if (!_iteratorNormalCompletion && _iterator['return']) {
                _iterator['return']();
              }
            } finally {
              if (_didIteratorError) {
                throw _iteratorError;
              }
            }
          }
        }
      }return transform && transform.input ? _Promise.all(records.map(function (record) {
        return transform.input(context, record);
      })) : _Promise.resolve(records);
    }).then(function (records) {
      return _Promise.all(records.map(function (record) {
        // Enforce the fields.
        (0, _record_typeEnforce2['default'])(type, record, fields);
  
        // Ensure referential integrity.
        return _check_links2['default'].call(_this, record, fields, links, meta).then(function () {
          return record;
        });
      })).then(function (records) {
        return _validate_records2['default'].call(_this, records, fields, links);
      }).then(function () {
        return adapter.beginTransaction();
      }).then(function (t) {
        transaction = t;
        return transaction.create(type, records, meta);
      });
    }).then(function (createdRecords) {
      records = createdRecords;
  
      Object.defineProperty(context.response, 'records', {
        configurable: true,
        value: records
      });
  
      // Adapter must return something.
      if (!records.length) throw new _commonErrors.BadRequestError('Records could not be created.');
  
      // Each created record must have an ID.
      if (records.some(function (record) {
        return !(_commonKeys.primary in record);
      })) throw new Error('An ID on a created record is missing.');
  
      // Update inversely linked records on created records.
      // Trying to batch updates to be as few as possible.
      var idCache = {};
  
      // Iterate over each record to generate updates object.
      var _iteratorNormalCompletion2 = true;
      var _didIteratorError2 = false;
      var _iteratorError2 = undefined;
  
      try {
        for (var _iterator2 = _getIterator(records), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
          var record = _step2.value;
          var _iteratorNormalCompletion3 = true;
          var _didIteratorError3 = false;
          var _iteratorError3 = undefined;
  
          try {
            for (var _iterator3 = _getIterator(links), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
              var field = _step3.value;
  
              var inverseField = fields[field][_commonKeys.inverse];
  
              if (!(field in record) || !inverseField) continue;
  
              var linkedType = fields[field][_commonKeys.link];
              var linkedIsArray = recordTypes[linkedType][inverseField][_commonKeys.isArray];
              var linkedIds = Array.isArray(record[field]) ? record[field] : [record[field]];
  
              // Do some initialization.
              if (!(linkedType in updates)) updates[linkedType] = [];
              if (!(linkedType in idCache)) idCache[linkedType] = new _Set();
  
              var _iteratorNormalCompletion4 = true;
              var _didIteratorError4 = false;
              var _iteratorError4 = undefined;
  
              try {
                for (var _iterator4 = _getIterator(linkedIds), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
                  var id = _step4.value;
  
                  if (id !== null) updateHelpers.addId(record[_commonKeys.primary], updateHelpers.getUpdate(linkedType, id, updates, idCache), inverseField, linkedIsArray);
                }
              } catch (err) {
                _didIteratorError4 = true;
                _iteratorError4 = err;
              } finally {
                try {
                  if (!_iteratorNormalCompletion4 && _iterator4['return']) {
                    _iterator4['return']();
                  }
                } finally {
                  if (_didIteratorError4) {
                    throw _iteratorError4;
                  }
                }
              }
            }
          } catch (err) {
            _didIteratorError3 = true;
            _iteratorError3 = err;
          } finally {
            try {
              if (!_iteratorNormalCompletion3 && _iterator3['return']) {
                _iterator3['return']();
              }
            } finally {
              if (_didIteratorError3) {
                throw _iteratorError3;
              }
            }
          }
        }
      } catch (err) {
        _didIteratorError2 = true;
        _iteratorError2 = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion2 && _iterator2['return']) {
            _iterator2['return']();
          }
        } finally {
          if (_didIteratorError2) {
            throw _iteratorError2;
          }
        }
      }
  
      return _Promise.all(_Object$keys(updates).map(function (type) {
        return updates[type].length ? transaction.update(type, updates[type], meta) : null;
      }));
    }).then(function () {
      return transaction.endTransaction();
    })['catch'](function (error) {
      if (transaction) transaction.endTransaction(error);
      throw error;
    }).then(function () {
      var eventData = _defineProperty({}, _commonMethods.create, _defineProperty({}, type, records.map(function (record) {
        return record[_commonKeys.primary];
      })));
  
      if (_Object$keys(updates).length) {
        eventData[_commonMethods.update] = {};
  
        for (var _type in updates) {
          if (!updates[_type].length) continue;
          eventData[_commonMethods.update][_type] = updates[_type].map(mapId);
        }
      }
  
      // Summarize changes during the lifecycle of the request.
      _this.emit(_commonChange2['default'], eventData);
  
      return context;
    });
  };
  
  function mapId(update) {
    return update[_commonKeys.primary];
  }
  module.exports = exports['default'];