react-transporter
Advanced tools
Comparing version 0.3.4 to 0.4.0
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.load = exports.Provider = exports.createTransporterSelector = exports.TransporterClient = exports.TransporterNetwork = undefined; | ||
exports.selectAdvanced = exports.selectByRoot = exports.selectByRelation = exports.select = exports.ManyLink = exports.Link = exports.load = exports.Provider = exports.TransporterClient = exports.TransporterNetwork = undefined; | ||
@@ -17,6 +17,2 @@ var _Network = require('./core/Network'); | ||
var _createSelector = require('./selector/createSelector'); | ||
var _createSelector2 = _interopRequireDefault(_createSelector); | ||
var _Provider = require('./react/Provider'); | ||
@@ -30,2 +26,26 @@ | ||
var _Link = require('./request/Link'); | ||
var _Link2 = _interopRequireDefault(_Link); | ||
var _ManyLink = require('./request/ManyLink'); | ||
var _ManyLink2 = _interopRequireDefault(_ManyLink); | ||
var _select = require('./selector/select'); | ||
var _select2 = _interopRequireDefault(_select); | ||
var _selectByRelation = require('./selector/selectByRelation'); | ||
var _selectByRelation2 = _interopRequireDefault(_selectByRelation); | ||
var _selectByRoot = require('./selector/selectByRoot'); | ||
var _selectByRoot2 = _interopRequireDefault(_selectByRoot); | ||
var _selectAdvanced = require('./selector/selectAdvanced'); | ||
var _selectAdvanced2 = _interopRequireDefault(_selectAdvanced); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -35,4 +55,9 @@ | ||
exports.TransporterClient = _Client2.default; | ||
exports.createTransporterSelector = _createSelector2.default; | ||
exports.Provider = _Provider2.default; | ||
exports.load = _load2.default; | ||
exports.load = _load2.default; | ||
exports.Link = _Link2.default; | ||
exports.ManyLink = _ManyLink2.default; | ||
exports.select = _select2.default; | ||
exports.selectByRelation = _selectByRelation2.default; | ||
exports.selectByRoot = _selectByRoot2.default; | ||
exports.selectAdvanced = _selectAdvanced2.default; |
@@ -9,2 +9,12 @@ 'use strict'; | ||
var _generateId = require('../utils/generateId'); | ||
var _generateId2 = _interopRequireDefault(_generateId); | ||
var _getPosition = require('../utils/getPosition'); | ||
var _getPosition2 = _interopRequireDefault(_getPosition); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -14,12 +24,11 @@ | ||
// TODO | ||
// parse a real graphql schema | ||
var parseSchema = function parseSchema(schema) { | ||
return schema; | ||
}; | ||
var getRequestName = function getRequestName(schema) { | ||
return schema; | ||
}; | ||
var TRANSPORTER_STATE = 'transporter'; | ||
function load(requestFunc) { | ||
function getStoredRequestById(id, requests) { | ||
var position = (0, _getPosition2.default)(id, requests); | ||
return position ? requests[position] : null; | ||
} | ||
function load(createRequest) { | ||
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
@@ -31,12 +40,13 @@ | ||
}; | ||
var request = requestFunc(props, fromState); | ||
var schema = parseSchema(request.schema); | ||
var requestName = getRequestName(schema); | ||
var request = createRequest(props, fromState); | ||
var requests = state.transporter.requests; | ||
// create request id if not present | ||
if (!request.id) request.id = (0, _generateId2.default)(); | ||
var storedRequest = getStoredRequestById(request.id, state[TRANSPORTER_STATE].requests); | ||
return { | ||
request: request, | ||
loading: requests[requestName] ? requests[requestName].loading : undefined, | ||
error: requests[requestName] ? requests[requestName].error : undefined | ||
loading: storedRequest ? storedRequest.loading : undefined, | ||
error: storedRequest ? storedRequest.error : undefined | ||
}; | ||
@@ -43,0 +53,0 @@ }; |
@@ -21,2 +21,3 @@ 'use strict'; | ||
/* eslint-disable react/prop-types */ | ||
var Provider = function (_React$Component) { | ||
@@ -34,3 +35,2 @@ _inherits(Provider, _React$Component); | ||
value: function render() { | ||
// eslint-disable-next-line react/prop-types | ||
return this.props.children; | ||
@@ -42,3 +42,4 @@ } | ||
}(_react2.default.Component); | ||
/* eslint-enable */ | ||
exports.default = Provider; |
@@ -7,32 +7,38 @@ 'use strict'; | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
exports.default = createReducer; | ||
exports.default = createEntitiesReducer; | ||
var _hasManyEntities = require('../utils/hasManyEntities'); | ||
var _getPosition = require('../utils/getPosition'); | ||
var _hasManyEntities2 = _interopRequireDefault(_hasManyEntities); | ||
var _getPosition2 = _interopRequireDefault(_getPosition); | ||
var _prependEntities = require('./utils/prependEntities'); | ||
var _isAmongEntities = require('./utils/isAmongEntities'); | ||
var _prependEntities2 = _interopRequireDefault(_prependEntities); | ||
var _isAmongEntities2 = _interopRequireDefault(_isAmongEntities); | ||
var _appendEntities = require('./utils/appendEntities'); | ||
var _addOptimisticUpdate = require('./utils/addOptimisticUpdate'); | ||
var _appendEntities2 = _interopRequireDefault(_appendEntities); | ||
var _addOptimisticUpdate2 = _interopRequireDefault(_addOptimisticUpdate); | ||
var _detachEntities = require('./utils/detachEntities'); | ||
var _revertOptimisticUpdate = require('./utils/revertOptimisticUpdate'); | ||
var _detachEntities2 = _interopRequireDefault(_detachEntities); | ||
var _revertOptimisticUpdate2 = _interopRequireDefault(_revertOptimisticUpdate); | ||
var _mergeEntities = require('./utils/mergeEntities'); | ||
var _updateValueBeforeRevertingOptimisticUpdate = require('./utils/updateValueBeforeRevertingOptimisticUpdate'); | ||
var _mergeEntities2 = _interopRequireDefault(_mergeEntities); | ||
var _updateValueBeforeRevertingOptimisticUpdate2 = _interopRequireDefault(_updateValueBeforeRevertingOptimisticUpdate); | ||
var _handleErrors = require('./utils/handleErrors'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function createReducer(entities) { | ||
var initialState = entities; | ||
function createEntitiesReducer(data) { | ||
var initialState = { | ||
data: data, | ||
optimistic: { | ||
updates: {}, | ||
deletions: {} | ||
} | ||
}; | ||
@@ -43,169 +49,177 @@ return function reducer() { | ||
if ((baseAction.type === 'TRANSPORTER_REQUEST_START' || baseAction.type === 'TRANSPORTER_REQUEST_COMPLETED') && baseAction.actions.entities && baseAction.actions.entities.length > 0) { | ||
var nextState = _extends({}, state); | ||
var nextState = _extends({}, state); | ||
var action = _extends({}, baseAction); | ||
baseAction.actions.entities.forEach(function (action) { | ||
switch (action.type) { | ||
// apply response | ||
case 'APPLY_RESPONSE': | ||
{ | ||
// merge entities | ||
Object.keys(action.entities).forEach(function (type) { | ||
if (!nextState[type]) { | ||
nextState[type] = {}; | ||
} | ||
Object.keys(action.entities[type]).forEach(function (id) { | ||
if (!nextState[type][id]) { | ||
// insert new entity | ||
nextState[type][id] = action.entities[type][id]; | ||
} else { | ||
// update entity | ||
nextState[type][id] = (0, _mergeEntities2.default)(state[type][id], action.entities[type][id]); | ||
} | ||
}); | ||
}); | ||
break; | ||
// TRANSPORTER_REQUEST_START | ||
// apply optimistic data | ||
if (action.type === 'TRANSPORTER_REQUEST_START' && action.optimisticData) { | ||
// insertions/updates | ||
if (action.optimisticData.entities) { | ||
Object.keys(action.optimisticData.entities).forEach(function (type) { | ||
// prerequisites / create (optimistic) type of entities if not present | ||
if (!nextState.data[type]) nextState.data[type] = {}; | ||
if (!nextState.optimistic.updates[type]) nextState.optimistic.updates[type] = {}; | ||
Object.keys(action.optimisticData.entities[type]).forEach(function (id) { | ||
// prerequisites / create optimistic entity if not present | ||
if (!nextState.optimistic.updates[type][id]) { | ||
nextState.optimistic.updates[type][id] = {}; | ||
} | ||
// insert entity | ||
case 'INSERT_ENTITY': | ||
{ | ||
var _action$entity = action.entity, | ||
type = _action$entity[0], | ||
id = _action$entity[1]; | ||
// error checks | ||
// add optimistic values | ||
Object.keys(action.optimisticData.entities[type][id]).forEach(function (field) { | ||
var getField = function getField(object) { | ||
if (!object[type] || !object[type][id]) return undefined; | ||
return object[type][id][field]; | ||
}; | ||
if (nextState[type] && nextState[type][id]) { | ||
(0, _handleErrors.throwInsertEntityError)(type, id); | ||
} | ||
// add optimistic update value | ||
nextState.optimistic.updates[type][id][field] = (0, _addOptimisticUpdate2.default)(nextState, action, getField); | ||
}); | ||
nextState[type][id] = {}; | ||
break; | ||
} | ||
// update entity | ||
case 'UPDATE_ENTITY': | ||
{ | ||
var _action$entity2 = action.entity, | ||
_type = _action$entity2[0], | ||
_id = _action$entity2[1]; | ||
// temporarily set stored value to optimistic value | ||
nextState.data[type][id] = Object.assign({}, nextState.data[type][id], action.optimisticData.entities[type][id]); | ||
}); | ||
}); | ||
} | ||
// error checks | ||
// deletions | ||
if (action.optimisticData.trash) { | ||
action.optimisticData.trash.forEach(function (_ref) { | ||
var _ref2 = _slicedToArray(_ref, 2), | ||
type = _ref2[0], | ||
id = _ref2[1]; | ||
if (!nextState[_type] || nextState[_type] && !nextState[_type][_id]) { | ||
(0, _handleErrors.throwUpdateEntityError)(_type, _id); | ||
} | ||
if (nextState.data[type] && nextState.data[type][id]) { | ||
// prerequisites / create optimistic type of entities if not present | ||
if (!nextState.optimistic.deletions[type]) nextState.optimistic.deletions[type] = {}; | ||
nextState[_type][_id] = Object.assign({}, nextState[_type][_id], action.data); | ||
break; | ||
} | ||
// delete entity | ||
case 'DELETE_ENTITY': | ||
{ | ||
var _action$entity3 = action.entity, | ||
_type2 = _action$entity3[0], | ||
_id2 = _action$entity3[1]; | ||
// add trashed entity to optimistically trashed entities | ||
nextState.optimistic.deletions[type][id] = { | ||
id: action.id, | ||
value: nextState.data[type][id] | ||
}; | ||
// error checks | ||
// temporarily delete entity | ||
delete nextState.data[type][id]; | ||
} | ||
}); | ||
} | ||
} | ||
if (!nextState[_type2] || nextState[_type2] && !nextState[_type2][_id2]) { | ||
(0, _handleErrors.throwDeleteEntityError)(_type2, _id2); | ||
// TRANSPORTER_REQUEST_COMPLETED || TRANSPORTER_REQUEST_ERROR | ||
// revert optimistic data & apply response data for specified fields | ||
if ((action.type === 'TRANSPORTER_REQUEST_COMPLETED' || action.type === 'TRANSPORTER_REQUEST_ERROR') && action.optimisticData) { | ||
// insertions/updates | ||
if (action.optimisticData.entities) { | ||
Object.keys(action.optimisticData.entities).forEach(function (type) { | ||
Object.keys(action.optimisticData.entities[type]).forEach(function (id) { | ||
Object.keys(action.optimisticData.entities[type][id]).forEach(function (field) { | ||
var getField = function getField(object) { | ||
if (!object[type] || !object[type][id]) return undefined; | ||
return object[type][id][field]; | ||
}; | ||
// get position of optimistic value & throw error if optimistic value was not found | ||
var position = (0, _getPosition2.default)(action.id, getField(nextState.optimistic.updates).values); | ||
if (position === -1) { | ||
throw new Error('Optimistic value not found.'); | ||
} | ||
nextState[_type2][_id2] = undefined; | ||
break; | ||
} | ||
// update connection | ||
case 'UPDATE_CONNECTION': | ||
{ | ||
var _action$entity4 = action.entity, | ||
_type3 = _action$entity4[0], | ||
_id3 = _action$entity4[1], | ||
name = action.name, | ||
linkedEntity = action.linkedEntity; | ||
// update stored value | ||
(0, _updateValueBeforeRevertingOptimisticUpdate2.default)(position, state, action, getField); | ||
// error checks | ||
if (!nextState[_type3] || nextState[_type3] && !nextState[_type3][_id3]) { | ||
(0, _handleErrors.throwUpdateConnectionError)(_type3, _id3, name); | ||
// revert optimistic value | ||
nextState.optimistic.updates[type][id][field] = (0, _revertOptimisticUpdate2.default)(position, state, action, getField); | ||
if (nextState.optimistic.updates[type][id][field] === undefined) { | ||
delete nextState.optimistic.updates[type][id][field]; | ||
} | ||
if (nextState[_type3][_id3][name] && nextState[_type3][_id3][name].linked && (0, _hasManyEntities2.default)(nextState[_type3][_id3][name].linked)) { | ||
(0, _handleErrors.throwWrongConnectionFormatError)(_type3, _id3, name); | ||
} | ||
// create relation if relation does not exist | ||
if (!nextState[_type3][_id3][name]) { | ||
nextState[_type3][_id3][name] = {}; | ||
// delete value from response if present | ||
if (action.data && action.data.entities && getField(action.data.entities)) { | ||
delete action.data.entities[type][id][field]; | ||
} | ||
}); | ||
nextState[_type3][_id3][name].linked = linkedEntity; | ||
break; | ||
// garbage collection | ||
if (Object.keys(nextState.optimistic.updates[type][id]).length === 0) { | ||
delete nextState.optimistic.updates[type][id]; | ||
} | ||
// update many connection | ||
case 'UPDATE_MANY_CONNECTION': | ||
{ | ||
var _action$entity5 = action.entity, | ||
_type4 = _action$entity5[0], | ||
_id4 = _action$entity5[1], | ||
_name = action.name, | ||
linkedEntities = action.linkedEntities; | ||
}); | ||
// error checks | ||
// garbage collection | ||
if (Object.keys(nextState.optimistic.updates[type]).length === 0) { | ||
delete nextState.optimistic.updates[type]; | ||
} | ||
}); | ||
} | ||
if (!nextState[_type4] || nextState[_type4] && !nextState[_type4][_id4]) { | ||
(0, _handleErrors.throwUpdateConnectionError)(_type4, _id4, _name); | ||
} | ||
if (nextState[_type4][_id4][_name] && nextState[_type4][_id4][_name].linked && !(0, _hasManyEntities2.default)(nextState[_type4][_id4][_name].linked)) { | ||
(0, _handleErrors.throwWrongManyConnectionFormatError)(_type4, _id4, _name); | ||
} | ||
// deletions | ||
if (action.optimisticData.trash) { | ||
action.optimisticData.trash.forEach(function (_ref3) { | ||
var _ref4 = _slicedToArray(_ref3, 2), | ||
type = _ref4[0], | ||
id = _ref4[1]; | ||
// create relation if relation does not exist | ||
if (!nextState[_type4][_id4][_name]) { | ||
nextState[_type4][_id4][_name] = {}; | ||
} | ||
// check if request id is correct | ||
if (nextState.optimistic.deletions[type][id].id !== action.id) { | ||
throw new Error('Optimistic deletion was processed by other request.'); | ||
} | ||
switch (action.method) { | ||
case 'sync_prepend': | ||
{ | ||
nextState[_type4][_id4][_name].linked = (0, _prependEntities2.default)(linkedEntities, nextState[_type4][_id4][_name].linked, true); | ||
break; | ||
} | ||
case 'sync_append': | ||
{ | ||
nextState[_type4][_id4][_name].linked = (0, _appendEntities2.default)(linkedEntities, nextState[_type4][_id4][_name].linked, true); | ||
break; | ||
} | ||
case 'prepend': | ||
{ | ||
nextState[_type4][_id4][_name].linked = (0, _prependEntities2.default)(linkedEntities, nextState[_type4][_id4][_name].linked); | ||
break; | ||
} | ||
case 'append': | ||
{ | ||
nextState[_type4][_id4][_name].linked = (0, _appendEntities2.default)(linkedEntities, nextState[_type4][_id4][_name].linked); | ||
break; | ||
} | ||
case 'detach': | ||
{ | ||
nextState[_type4][_id4][_name].linked = (0, _detachEntities2.default)(linkedEntities, nextState[_type4][_id4][_name].linked); | ||
break; | ||
} | ||
default: | ||
{ | ||
// do nothing | ||
} | ||
} | ||
break; | ||
} | ||
default: | ||
{ | ||
// do nothing | ||
} | ||
} | ||
}); | ||
// check if optimistic deletion is in response too | ||
var position = action.data && action.data.trash ? (0, _isAmongEntities2.default)([type, id], action.data.trash) : -1; | ||
if (position !== -1) { | ||
// if yes -> delete entity from response | ||
delete action.data.trash[position]; | ||
} else { | ||
// if no -> restore entity | ||
// prerequisites / create type of entities if not present | ||
if (!nextState.data[type]) nextState.data[type] = {}; | ||
return nextState; | ||
// set entity | ||
nextState.data[type][id] = nextState.optimistic.deletions[type][id].value; | ||
} | ||
// finally delete entity from optimistic data | ||
delete nextState.optimistic.deletions[type][id]; | ||
if (Object.keys(nextState.optimistic.deletions[type]).length === 0) { | ||
delete nextState.optimistic.deletions[type]; | ||
} | ||
}); | ||
} | ||
} | ||
return state; | ||
// TRANSPORTER_REQUEST_COMPLETED | ||
// apply response data | ||
if (action.type === 'TRANSPORTER_REQUEST_COMPLETED') { | ||
// insertions/updates | ||
if (action.data.entities) { | ||
Object.keys(action.data.entities).forEach(function (type) { | ||
// prerequisites / create type of entities if not present | ||
if (!nextState.data[type]) nextState.data[type] = {}; | ||
Object.keys(action.data.entities[type]).forEach(function (id) { | ||
// add entity to store | ||
nextState.data[type][id] = Object.assign({}, nextState.data[type][id], action.data.entities[type][id]); | ||
}); | ||
}); | ||
} | ||
// deletions | ||
if (action.data.trash) { | ||
action.data.trash.forEach(function (_ref5) { | ||
var _ref6 = _slicedToArray(_ref5, 2), | ||
type = _ref6[0], | ||
id = _ref6[1]; | ||
// delete entity from store | ||
if (nextState.data[type] && nextState.data[type][id]) { | ||
delete nextState.data[type][id]; | ||
} | ||
}); | ||
} | ||
} | ||
return nextState; | ||
}; | ||
} |
@@ -9,9 +9,15 @@ 'use strict'; | ||
exports.default = createReducer; | ||
exports.default = createRequestsReducer; | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var _getPosition = require('../utils/getPosition'); | ||
function createReducer() { | ||
var initialState = {}; | ||
var _getPosition2 = _interopRequireDefault(_getPosition); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
function createRequestsReducer() { | ||
var initialState = []; | ||
return function reducer() { | ||
@@ -21,30 +27,38 @@ var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; | ||
switch (action.type) { | ||
case 'TRANSPORTER_REQUEST_START': | ||
{ | ||
return _extends({}, state, _defineProperty({}, action.name, { | ||
loading: true, | ||
error: null | ||
})); | ||
} | ||
case 'TRANSPORTER_REQUEST_COMPLETED': | ||
{ | ||
return _extends({}, state, _defineProperty({}, action.name, { | ||
loading: false, | ||
error: null | ||
})); | ||
} | ||
case 'TRANSPORTER_REQUEST_ERROR': | ||
{ | ||
return _extends({}, state, _defineProperty({}, action.name, { | ||
loading: false, | ||
error: action.error | ||
})); | ||
} | ||
default: | ||
{ | ||
return state; | ||
} | ||
var nextState = [].concat(_toConsumableArray(state)); | ||
// TRANSPORTER_REQUEST_START | ||
if (action.type === 'TRANSPORTER_REQUEST_START') { | ||
nextState.push({ | ||
id: action.id, | ||
startTime: action.startTime, | ||
endTime: null, | ||
loading: true, | ||
error: null | ||
}); | ||
} | ||
// TRANSPORTER_REQUEST_COMPLETED | ||
if (action.type === 'TRANSPORTER_REQUEST_COMPLETED') { | ||
var position = (0, _getPosition2.default)(action.id, nextState); | ||
nextState[position] = _extends({}, nextState[position], { | ||
endTime: action.endTime, | ||
loading: false | ||
}); | ||
} | ||
// TRANSPORTER_REQUEST_ERROR | ||
if (action.type === 'TRANSPORTER_REQUEST_COMPLETED') { | ||
var _position = (0, _getPosition2.default)(action.id, nextState); | ||
nextState[_position] = _extends({}, nextState[_position], { | ||
endTime: action.endTime, | ||
loading: false, | ||
error: action.error | ||
}); | ||
} | ||
return nextState; | ||
}; | ||
} |
@@ -9,26 +9,26 @@ 'use strict'; | ||
exports.default = createReducer; | ||
exports.default = createRootsReducer; | ||
var _hasManyEntities = require('../utils/hasManyEntities'); | ||
var _getPosition = require('../utils/getPosition'); | ||
var _hasManyEntities2 = _interopRequireDefault(_hasManyEntities); | ||
var _getPosition2 = _interopRequireDefault(_getPosition); | ||
var _prependEntities = require('./utils/prependEntities'); | ||
var _addOptimisticUpdate = require('./utils/addOptimisticUpdate'); | ||
var _prependEntities2 = _interopRequireDefault(_prependEntities); | ||
var _addOptimisticUpdate2 = _interopRequireDefault(_addOptimisticUpdate); | ||
var _appendEntities = require('./utils/appendEntities'); | ||
var _revertOptimisticUpdate = require('./utils/revertOptimisticUpdate'); | ||
var _appendEntities2 = _interopRequireDefault(_appendEntities); | ||
var _revertOptimisticUpdate2 = _interopRequireDefault(_revertOptimisticUpdate); | ||
var _detachEntities = require('./utils/detachEntities'); | ||
var _detachEntities2 = _interopRequireDefault(_detachEntities); | ||
var _handleErrors = require('./utils/handleErrors'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function createReducer(roots) { | ||
var initialState = roots; | ||
function createRootsReducer(data) { | ||
var initialState = { | ||
data: data, | ||
optimistic: { | ||
updates: {}, | ||
deletions: {} | ||
} | ||
}; | ||
@@ -39,99 +39,57 @@ return function reducer() { | ||
if ((baseAction.type === 'TRANSPORTER_REQUEST_START' || baseAction.type === 'TRANSPORTER_REQUEST_COMPLETED') && baseAction.actions.roots && baseAction.actions.roots.length > 0) { | ||
var nextState = _extends({}, state); | ||
var nextState = _extends({}, state); | ||
var action = _extends({}, baseAction); | ||
baseAction.actions.roots.forEach(function (action) { | ||
switch (action.type) { | ||
// apply response | ||
case 'APPLY_RESPONSE': | ||
{ | ||
Object.keys(action.data).forEach(function (name) { | ||
if (nextState[name] && nextState[name].linked) { | ||
nextState[name].linked = nextState[name].linked.concat(action.data[name].linked); | ||
} else { | ||
nextState[name] = { | ||
linked: action.data[name].linked | ||
}; | ||
} | ||
}); | ||
break; | ||
} | ||
// update connection | ||
case 'UPDATE_CONNECTION': | ||
{ | ||
var name = action.name, | ||
linkedEntity = action.linkedEntity; | ||
// TRANSPORTER_REQUEST_START | ||
// apply optimistic data | ||
if (action.type === 'TRANSPORTER_REQUEST_START' && action.optimisticData && action.optimisticData.roots) { | ||
Object.keys(action.optimisticData.roots).forEach(function (root) { | ||
var getRoot = function getRoot(object) { | ||
return object[root]; | ||
}; | ||
// error checks | ||
// add optimistic update value | ||
nextState.optimistic.updates[root] = (0, _addOptimisticUpdate2.default)(nextState, action, getRoot, true); | ||
}); | ||
if (!nextState[name]) { | ||
(0, _handleErrors.throwUpdateRootConnectionError)(name); | ||
} | ||
if (nextState[name].linked && (0, _hasManyEntities2.default)(nextState[name].linked)) { | ||
(0, _handleErrors.throwWrongRootConnectionFormatError)(name); | ||
} | ||
// temporarily set stored value to optimistic value | ||
nextState.data = Object.assign({}, nextState.data, action.optimisticData.roots); | ||
} | ||
nextState[name].linked = linkedEntity; | ||
break; | ||
} | ||
// update many connection | ||
case 'UPDATE_MANY_CONNECTION': | ||
{ | ||
var _name = action.name, | ||
linkedEntities = action.linkedEntities; | ||
// TRANSPORTER_REQUEST_COMPLETED || TRANSPORTER_REQUEST_ERROR | ||
// revert optimistic data & apply response data for specified fields | ||
if ((action.type === 'TRANSPORTER_REQUEST_COMPLETED' || action.type === 'TRANSPORTER_REQUEST_ERROR') && action.optimisticData && action.optimisticData.roots) { | ||
Object.keys(action.optimisticData.roots).forEach(function (root) { | ||
var getRoot = function getRoot(object) { | ||
return object[root]; | ||
}; | ||
// error checks | ||
// get position of optimistic value & throw error if optimistic value was not found | ||
var position = (0, _getPosition2.default)(action.id, getRoot(nextState.optimistic.updates).values); | ||
if (position === -1) { | ||
throw new Error('Optimistic value not found.'); | ||
} | ||
if (!nextState[_name]) { | ||
(0, _handleErrors.throwUpdateRootConnectionError)(_name); | ||
} | ||
if (nextState[_name].linked && !(0, _hasManyEntities2.default)(nextState[_name].linked)) { | ||
(0, _handleErrors.throwWrongManyRootConnectionFormatError)(_name); | ||
} | ||
// revert optimistic value | ||
nextState.optimistic.updates[root] = (0, _revertOptimisticUpdate2.default)(position, state, action, getRoot, true); | ||
if (nextState.optimistic.updates[root] === undefined) { | ||
delete nextState.optimistic.updates[root]; | ||
} | ||
switch (action.method) { | ||
case 'sync_prepend': | ||
{ | ||
nextState[_name].linked = (0, _prependEntities2.default)(linkedEntities, nextState[_name].linked, true); | ||
break; | ||
} | ||
case 'sync_append': | ||
{ | ||
nextState[_name].linked = (0, _appendEntities2.default)(linkedEntities, nextState[_name].linked, true); | ||
break; | ||
} | ||
case 'prepend': | ||
{ | ||
nextState[_name].linked = (0, _prependEntities2.default)(linkedEntities, nextState[_name].linked); | ||
break; | ||
} | ||
case 'append': | ||
{ | ||
nextState[_name].linked = (0, _appendEntities2.default)(linkedEntities, nextState[_name].linked); | ||
break; | ||
} | ||
case 'detach': | ||
{ | ||
nextState[_name].linked = (0, _detachEntities2.default)(linkedEntities, nextState[_name].linked); | ||
break; | ||
} | ||
default: | ||
{ | ||
// do nothing | ||
} | ||
} | ||
break; | ||
} | ||
default: | ||
{ | ||
// do nothing | ||
} | ||
// delete value from response if present | ||
if (action.data && action.data.roots && getRoot(action.data.roots)) { | ||
delete action.data.roots[root]; | ||
} | ||
}); | ||
} | ||
return nextState; | ||
// TRANSPORTER_REQUEST_COMPLETED | ||
// apply response data | ||
if (action.type === 'TRANSPORTER_REQUEST_COMPLETED' && action.data.roots) { | ||
// add root to store | ||
nextState.data = Object.assign({}, nextState.data, action.data.roots); | ||
} | ||
return state; | ||
return nextState; | ||
}; | ||
} |
@@ -8,66 +8,41 @@ 'use strict'; | ||
var _ActionCollector = require('./ActionCollector'); | ||
var _generateId = require('../utils/generateId'); | ||
var _ActionCollector2 = _interopRequireDefault(_ActionCollector); | ||
var _generateId2 = _interopRequireDefault(_generateId); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _WriteStore = require('./WriteStore'); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var _WriteStore2 = _interopRequireDefault(_WriteStore); | ||
// TODO | ||
// parse a real graphql schema | ||
var parseSchema = function parseSchema(schema) { | ||
return schema; | ||
}; | ||
var getRequestName = function getRequestName(schema) { | ||
return schema; | ||
}; | ||
var getRootNames = function getRootNames(schema) { | ||
return [schema]; | ||
}; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var createOptimistcResponse = function createOptimistcResponse(rootNames) { | ||
return { | ||
roots: rootNames.map(function (rootName) { | ||
return _defineProperty({}, rootName, { | ||
linked: null | ||
}); | ||
}) | ||
}; | ||
}; | ||
var TRANSPORTER_STATE = 'transporter'; | ||
function createRequest(request, fetch) { | ||
var schema = parseSchema(request.schema); | ||
var requestName = getRequestName(schema); | ||
var rootNames = getRootNames(schema); | ||
function makeData(updater, getState, response) { | ||
if (!updater) { | ||
return response; | ||
} | ||
return function (dispatch) { | ||
// init request and apply optimistc response if set | ||
var optimisticActions = new _ActionCollector2.default(); | ||
var state = getState(); | ||
// add optimistic response for mutations | ||
if (request.type === 'TRANSPORTER_MUTATION' && request.optimisticUpdater) { | ||
optimisticActions.applyResponse(createOptimistcResponse(rootNames)); | ||
optimisticActions.applyUpdater(request.optimisticUpdater); | ||
} | ||
var store = new _WriteStore2.default(state[TRANSPORTER_STATE], response); | ||
updater(store, response); // TODO only pass in root and trashed ids of response | ||
return store.data; | ||
} | ||
try { | ||
dispatch({ | ||
type: 'TRANSPORTER_REQUEST_START', | ||
name: requestName, | ||
actions: optimisticActions.getActions() | ||
}); | ||
} catch (error) { | ||
// eslint-disable-next-line no-console | ||
console.error(error.message); | ||
function createRequest(request, fetch) { | ||
return function (dispatch, getState) { | ||
// create request id if not present | ||
if (!request.id) request.id = (0, _generateId2.default)(); | ||
var startTime = new Date(); | ||
var data = request.type === 'TRANSPORTER_MUTATION' ? makeData(request.optimisticUpdater, getState) : {}; | ||
var optimisticData = request.type === 'TRANSPORTER_MUTATION' ? data : null; | ||
dispatch({ | ||
type: 'TRANSPORTER_REQUEST_ERROR', | ||
name: requestName, | ||
error: error | ||
}); | ||
dispatch({ | ||
type: 'TRANSPORTER_REQUEST_START', | ||
id: request.id, | ||
startTime: startTime, | ||
optimisticData: optimisticData | ||
}); | ||
return; | ||
} | ||
// immediately stop request on server for now | ||
@@ -78,4 +53,6 @@ // TODO | ||
type: 'TRANSPORTER_REQUEST_COMPLETED', | ||
name: requestName, | ||
actions: [] | ||
id: request.id, | ||
startTime: startTime, | ||
endTime: new Date(), | ||
data: data | ||
}); | ||
@@ -88,23 +65,21 @@ } | ||
// dispatch query | ||
fetch(request.schema, request.variables).then(function (response) { | ||
// integrate response into store on success | ||
var actions = new _ActionCollector2.default(); | ||
if (response) actions.applyResponse(response); | ||
if (request.updater) actions.applyUpdater(request.updater, response); | ||
fetch(request.schema, request.variables).then(function () { | ||
try { | ||
dispatch({ | ||
type: 'TRANSPORTER_REQUEST_COMPLETED', | ||
name: requestName, | ||
actions: actions.getActions() | ||
id: request.id, | ||
endTime: new Date(), | ||
optimisticData: optimisticData, | ||
data: data | ||
}); | ||
} catch (error) { | ||
// eslint-disable-next-line no-console | ||
console.error(error); | ||
dispatch({ | ||
type: 'TRANSPORTER_REQUEST_ERROR', | ||
name: requestName, | ||
error: error | ||
id: request.id, | ||
endTime: new Date(), | ||
optimisticData: optimisticData, | ||
error: 'Internal error' | ||
}); | ||
throw error; | ||
} | ||
@@ -115,3 +90,5 @@ }, function (error) { | ||
type: 'TRANSPORTER_REQUEST_ERROR', | ||
name: requestName, | ||
id: request.id, | ||
endTime: new Date(), | ||
optimisticData: optimisticData, | ||
error: error | ||
@@ -118,0 +95,0 @@ }); |
@@ -8,14 +8,14 @@ 'use strict'; | ||
var _SelectorFactory = require('./SelectorFactory'); | ||
var _ReadStore = require('./ReadStore'); | ||
var _SelectorFactory2 = _interopRequireDefault(_SelectorFactory); | ||
var _ReadStore2 = _interopRequireDefault(_ReadStore); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var TRANSPORTER_STATE = 'transporter'; | ||
function createSelector(callback) { | ||
return function (state, props) { | ||
var selector = callback(new _SelectorFactory2.default(state.transporter), props); | ||
return selector.getData(); | ||
return callback(new _ReadStore2.default(state[TRANSPORTER_STATE]), props); | ||
}; | ||
} |
@@ -9,5 +9,5 @@ 'use strict'; | ||
var _hasManyEntities = require('../utils/hasManyEntities'); | ||
var _isManyLink = require('../utils/isManyLink'); | ||
var _hasManyEntities2 = _interopRequireDefault(_hasManyEntities); | ||
var _isManyLink2 = _interopRequireDefault(_isManyLink); | ||
@@ -30,13 +30,13 @@ var _compareValues = require('./utils/compareValues'); | ||
var Selector = function () { | ||
function Selector(state, data) { | ||
_classCallCheck(this, Selector); | ||
var StoreQuery = function () { | ||
function StoreQuery(state, data) { | ||
_classCallCheck(this, StoreQuery); | ||
this.hasManyEntities = (0, _hasManyEntities2.default)(data); | ||
this.isManyLink = (0, _isManyLink2.default)(data); | ||
this.data = this.hasManyEntities ? data.map(function (typeId) { | ||
return (0, _formatData2.default)(typeId[0], typeId[1], state.entities); | ||
this.data = this.isManyLink ? data.map(function (typeId) { | ||
return (0, _formatData2.default)(typeId[0], typeId[1], state.entities.data); | ||
}).filter(function (item) { | ||
return item !== undefined; | ||
}) : (0, _formatData2.default)(data[0], data[1], state.entities); | ||
}) : (0, _formatData2.default)(data[0], data[1], state.entities.data); | ||
@@ -46,3 +46,3 @@ this.state = state; | ||
_createClass(Selector, [{ | ||
_createClass(StoreQuery, [{ | ||
key: 'where', | ||
@@ -53,3 +53,3 @@ value: function where(attribute, inputOperator, inputValue) { | ||
if (!this.hasManyEntities) { | ||
if (!this.isManyLink) { | ||
if (!(0, _compareValues2.default)(this.data[attribute], operator, value)) { | ||
@@ -59,3 +59,3 @@ this.data = null; | ||
} | ||
if (this.hasManyEntities) { | ||
if (this.isManyLink) { | ||
this.data = this.data.filter(function (data) { | ||
@@ -95,3 +95,3 @@ return (0, _compareValues2.default)(data[attribute], operator, value); | ||
if (this.hasManyEntities) { | ||
if (this.isManyLink) { | ||
this.data.forEach(function (attributes, key) { | ||
@@ -119,5 +119,5 @@ if (_this.data[key]) { | ||
return Selector; | ||
return StoreQuery; | ||
}(); | ||
exports.default = Selector; | ||
exports.default = StoreQuery; |
@@ -7,2 +7,9 @@ 'use strict'; | ||
exports.default = compareValues; | ||
var _makeSelectorError = require('../makeSelectorError'); | ||
var _makeSelectorError2 = _interopRequireDefault(_makeSelectorError); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function compareValues(valueA, operator, valueB) { | ||
@@ -25,3 +32,3 @@ if (operator === '=') { | ||
throw new Error('Unknown operator "' + operator + '"'); | ||
throw (0, _makeSelectorError2.default)('UNKNOWN_WHERE_OPERATOR', { operator: operator }); | ||
} |
@@ -11,4 +11,12 @@ 'use strict'; | ||
var _handleErrors = require('./handleErrors'); | ||
var _makeSelectorError = require('../makeSelectorError'); | ||
var _makeSelectorError2 = _interopRequireDefault(_makeSelectorError); | ||
var _isConnection = require('../../utils/isConnection'); | ||
var _isConnection2 = _interopRequireDefault(_isConnection); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function formatData(type, id, entities) { | ||
@@ -20,5 +28,4 @@ var shallow = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; | ||
// log warning if entity does not exist | ||
if (!entities[type] || entities[type] && !entities[type][id]) { | ||
(0, _handleErrors.logSelectLinkedEntityWarning)(type, id); | ||
return undefined; | ||
if (!entities[type] || !entities[type][id]) { | ||
throw (0, _makeSelectorError2.default)('MISSING_JOINED_ENTITY', { type: type, id: id }); | ||
} | ||
@@ -32,3 +39,3 @@ | ||
Object.keys(entity).forEach(function (key) { | ||
if (entity[key] !== null && entity[key] !== undefined && !entity[key].linked) { | ||
if (!(0, _isConnection2.default)(entity[key])) { | ||
attributes[key] = entity[key]; | ||
@@ -35,0 +42,0 @@ } |
@@ -8,10 +8,14 @@ 'use strict'; | ||
var _Selector = require('./../Selector'); | ||
var _StoreQuery = require('./../StoreQuery'); | ||
var _Selector2 = _interopRequireDefault(_Selector); | ||
var _StoreQuery2 = _interopRequireDefault(_StoreQuery); | ||
var _hasManyEntities = require('../../utils/hasManyEntities'); | ||
var _isConnection = require('../../utils/isConnection'); | ||
var _hasManyEntities2 = _interopRequireDefault(_hasManyEntities); | ||
var _isConnection2 = _interopRequireDefault(_isConnection); | ||
var _isManyLink = require('../../utils/isManyLink'); | ||
var _isManyLink2 = _interopRequireDefault(_isManyLink); | ||
var _formatData = require('./formatData'); | ||
@@ -21,4 +25,6 @@ | ||
var _handleErrors = require('./handleErrors'); | ||
var _makeSelectorError = require('../makeSelectorError'); | ||
var _makeSelectorError2 = _interopRequireDefault(_makeSelectorError); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -28,24 +34,21 @@ | ||
// log warning if relation does not exist | ||
if (!state.entities[type][id][name] || state.entities[type][id][name] && state.entities[type][id][name].linked === undefined) { | ||
// eslint-disable-next-line no-console | ||
console.log(state.entities[type][id][name]); | ||
(0, _handleErrors.logSelectRelationWarning)(type, id, name); | ||
return undefined; | ||
if (!state.entities.data[type][id][name] || !(0, _isConnection2.default)(state.entities.data[type][id][name])) { | ||
throw (0, _makeSelectorError2.default)('MISSING_JOINED_RELATION', { type: type, id: id, name: name }); | ||
} | ||
var childrenTypeIds = state.entities.data[type][id][name].link; | ||
// relation is set to null | ||
if (state.entities[type][id][name].linked === null) { | ||
if (childrenTypeIds === null) { | ||
return null; | ||
} | ||
var childrenTypeIds = state.entities[type][id][name].linked; | ||
// only select shallow linked entities | ||
// only select shallow link entities | ||
if (shallow) { | ||
if (!(0, _hasManyEntities2.default)(childrenTypeIds)) { | ||
return (0, _formatData2.default)(childrenTypeIds[0], childrenTypeIds[1], state.entities, true); | ||
if (!(0, _isManyLink2.default)(childrenTypeIds)) { | ||
return (0, _formatData2.default)(childrenTypeIds[0], childrenTypeIds[1], state.entities.data, true); | ||
} | ||
return childrenTypeIds.map(function (childrenId) { | ||
return (0, _formatData2.default)(childrenId[0], childrenId[1], state.entities, true); | ||
return (0, _formatData2.default)(childrenId[0], childrenId[1], state.entities.data, true); | ||
}).filter(function (item) { | ||
@@ -57,5 +60,5 @@ return item !== undefined; | ||
// select full entity | ||
var selector = constraints ? constraints(new _Selector2.default(state, childrenTypeIds)) : new _Selector2.default(state, childrenTypeIds); | ||
var selector = constraints ? constraints(new _StoreQuery2.default(state, childrenTypeIds)) : new _StoreQuery2.default(state, childrenTypeIds); | ||
return selector.getData(); | ||
} |
{ | ||
"name": "react-transporter", | ||
"version": "0.3.4", | ||
"version": "0.4.0", | ||
"main": "./lib/index.js", | ||
@@ -18,12 +18,9 @@ "description": "React.js Redux GraphQL client", | ||
}, | ||
"dependencies": { | ||
"graphql": "^0.11.7", | ||
"graphql-tag": "^2.5.0" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"babel-cli": "6.26.0", | ||
"eslint": "4.9.0", | ||
"react": "16.1.0", | ||
"react-dom": "16.1.0", | ||
"react-kickstarter": "0.3.1", | ||
"react": "16.2.0", | ||
"react-dom": "16.2.0", | ||
"react-kickstarter": "0.3.4", | ||
"react-redux": "5.0.6", | ||
@@ -35,2 +32,3 @@ "redux": "3.7.2", | ||
"react": ">=15", | ||
"react-async-bootstrapper": ">=1", | ||
"react-dom": ">=15", | ||
@@ -37,0 +35,0 @@ "react-redux": ">=5", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
360620
6
107
3313
+ Addedobject-assign@4.1.1(transitive)
+ Addedprop-types@15.8.1(transitive)
+ Addedreact@16.14.0(transitive)
+ Addedreact-async-bootstrapper@2.1.1(transitive)
+ Addedreact-dom@16.14.0(transitive)
+ Addedreact-is@16.13.1(transitive)
+ Addedreact-tree-walker@4.3.0(transitive)
+ Addedscheduler@0.19.1(transitive)
- Removedgraphql@^0.11.7
- Removedgraphql-tag@^2.5.0
- Removedgraphql@0.11.7(transitive)
- Removedgraphql-tag@2.12.6(transitive)
- Removediterall@1.1.3(transitive)
- Removedtslib@2.8.1(transitive)