redux-saga-resources
Advanced tools
Comparing version 0.1.0 to 0.1.1
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
exports.default = actions; | ||
@@ -7,0 +5,0 @@ |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
exports.default = creators; | ||
function creators(name, actions) { | ||
return { | ||
doCreate: item => ({ type: actions.CREATE, payload: { item: item } }), | ||
doCreateCancel: item => ({ type: actions.CREATE_CANCEL, payload: { item: item } }), | ||
doCreateSuccess: item => ({ type: actions.CREATE_SUCCESS, payload: { item: item } }), | ||
doCreateFailure: (item, reason) => ({ type: actions.CREATE_FAILURE, payload: { item: item, reason: reason } }), | ||
doCreate: function doCreate(item) { | ||
return { type: actions.CREATE, payload: { item: item } }; | ||
}, | ||
doCreateCancel: function doCreateCancel(item) { | ||
return { type: actions.CREATE_CANCEL, payload: { item: item } }; | ||
}, | ||
doCreateSuccess: function doCreateSuccess(item) { | ||
return { type: actions.CREATE_SUCCESS, payload: { item: item } }; | ||
}, | ||
doCreateFailure: function doCreateFailure(item, reason) { | ||
return { type: actions.CREATE_FAILURE, payload: { item: item, reason: reason } }; | ||
}, | ||
doRead: item => ({ type: actions.READ, payload: { item: item } }), | ||
doReadCancel: item => ({ type: actions.READ_CANCEL, payload: { item: item } }), | ||
doReadSuccess: item => ({ type: actions.READ_SUCCESS, payload: { item: item } }), | ||
doReadFailure: (item, reason) => ({ type: actions.READ_FAILURE, payload: { item: item, reason: reason } }), | ||
doRead: function doRead(item) { | ||
return { type: actions.READ, payload: { item: item } }; | ||
}, | ||
doReadCancel: function doReadCancel(item) { | ||
return { type: actions.READ_CANCEL, payload: { item: item } }; | ||
}, | ||
doReadSuccess: function doReadSuccess(item) { | ||
return { type: actions.READ_SUCCESS, payload: { item: item } }; | ||
}, | ||
doReadFailure: function doReadFailure(item, reason) { | ||
return { type: actions.READ_FAILURE, payload: { item: item, reason: reason } }; | ||
}, | ||
doUpdate: item => ({ type: actions.UPDATE, payload: { item: item } }), | ||
doUpdateCancel: item => ({ type: actions.UPDATE_CANCEL, payload: { item: item } }), | ||
doUpdateSuccess: item => ({ type: actions.UPDATE_SUCCESS, payload: { item: item } }), | ||
doUpdateFailure: (item, reason) => ({ type: actions.UPDATE_FAILURE, payload: { item: item, reason: reason } }), | ||
doUpdate: function doUpdate(item) { | ||
return { type: actions.UPDATE, payload: { item: item } }; | ||
}, | ||
doUpdateCancel: function doUpdateCancel(item) { | ||
return { type: actions.UPDATE_CANCEL, payload: { item: item } }; | ||
}, | ||
doUpdateSuccess: function doUpdateSuccess(item) { | ||
return { type: actions.UPDATE_SUCCESS, payload: { item: item } }; | ||
}, | ||
doUpdateFailure: function doUpdateFailure(item, reason) { | ||
return { type: actions.UPDATE_FAILURE, payload: { item: item, reason: reason } }; | ||
}, | ||
doDelete: item => ({ type: actions.DELETE, payload: { item: item } }), | ||
doDeleteCancel: item => ({ type: actions.DELETE_CANCEL, payload: { item: item } }), | ||
doDeleteSuccess: item => ({ type: actions.DELETE_SUCCESS, payload: { item: item } }), | ||
doDeleteFailure: (item, reason) => ({ type: actions.DELETE_FAILURE, payload: { item: item, reason: reason } }), | ||
doDelete: function doDelete(item) { | ||
return { type: actions.DELETE, payload: { item: item } }; | ||
}, | ||
doDeleteCancel: function doDeleteCancel(item) { | ||
return { type: actions.DELETE_CANCEL, payload: { item: item } }; | ||
}, | ||
doDeleteSuccess: function doDeleteSuccess(item) { | ||
return { type: actions.DELETE_SUCCESS, payload: { item: item } }; | ||
}, | ||
doDeleteFailure: function doDeleteFailure(item, reason) { | ||
return { type: actions.DELETE_FAILURE, payload: { item: item, reason: reason } }; | ||
}, | ||
doList: () => ({ type: actions.LIST, payload: {} }), | ||
doListCancel: () => ({ type: actions.LIST_CANCEL, payload: {} }), | ||
doListSuccess: list => ({ type: actions.LIST_SUCCESS, payload: { list: list } }), | ||
doListFailure: reason => ({ type: actions.LIST_FAILURE, payload: { reason: reason } }), | ||
doList: function doList() { | ||
return { type: actions.LIST, payload: {} }; | ||
}, | ||
doListCancel: function doListCancel() { | ||
return { type: actions.LIST_CANCEL, payload: {} }; | ||
}, | ||
doListSuccess: function doListSuccess(list) { | ||
return { type: actions.LIST_SUCCESS, payload: { list: list } }; | ||
}, | ||
doListFailure: function doListFailure(reason) { | ||
return { type: actions.LIST_FAILURE, payload: { reason: reason } }; | ||
}, | ||
doReset: () => ({ type: actions.RESET }) | ||
doReset: function doReset() { | ||
return { type: actions.RESET }; | ||
} | ||
}; | ||
} |
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
@@ -17,16 +15,31 @@ 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; }; | ||
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 requireId = function requireId(item) { | ||
if (!item) { | ||
throw new Error('Expecting item.'); | ||
} | ||
var id = item[_fields.fields.id]; | ||
let ensureId = item => { | ||
if (!(_fields.fields.id in item)) { | ||
if (!id) { | ||
throw new Error('Expecting id to be filled, use resource.create({ ... }) to create a new instance.'); | ||
} | ||
return id; | ||
}; | ||
var requireTempId = function requireTempId(item) { | ||
if (!item) { | ||
throw new Error('Expecting item.'); | ||
} | ||
var tempId = item[_fields.fields.tempId]; | ||
if (!tempId) { | ||
throw new Error('Expecting tempId to be filled, use resource.create({ ... }) to create a new instance.'); | ||
} | ||
return tempId; | ||
}; | ||
function reducer(descriptor) { | ||
let actions = descriptor.actions; | ||
var actions = descriptor.actions; | ||
return function () { | ||
let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { loading: false, error: null, list: [] }; | ||
let action = arguments[1]; | ||
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { loading: false, error: null, list: [] }; | ||
var action = arguments[1]; | ||
@@ -37,8 +50,8 @@ switch (action.type) { | ||
// CREATE | ||
ensureId(action.payload.item); | ||
var internalId = requireTempId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends2; | ||
return _extends({}, item, action.payload.item, (_extends2 = {}, _defineProperty(_extends2, _fields.fields.error, null), _defineProperty(_extends2, _fields.fields.isModified, true), _defineProperty(_extends2, _fields.fields.isCreating, true), _extends2)); | ||
return _extends({}, item, action.payload.item, (_extends2 = {}, _extends2[_fields.fields.error] = null, _extends2[_fields.fields.isModified] = true, _extends2[_fields.fields.isCreating] = true, _extends2)); | ||
}) | ||
@@ -50,8 +63,8 @@ }); | ||
// CREATE - SUCCESS | ||
ensureId(action.payload.item); | ||
var _internalId = requireTempId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends3; | ||
return _extends({}, item, action.payload.item, (_extends3 = {}, _defineProperty(_extends3, _fields.fields.id, action.payload.item[_fields.fields.newId] || action.payload.item[_fields.fields.id]), _defineProperty(_extends3, _fields.fields.newId, null), _defineProperty(_extends3, _fields.fields.error, null), _defineProperty(_extends3, _fields.fields.isModified, false), _defineProperty(_extends3, _fields.fields.isCreating, false), _defineProperty(_extends3, _fields.fields.isCreated, true), _extends3)); | ||
return _extends({}, item, action.payload.item, (_extends3 = {}, _extends3[_fields.fields.error] = null, _extends3[_fields.fields.isModified] = false, _extends3[_fields.fields.isCreating] = false, _extends3[_fields.fields.isCreated] = true, _extends3)); | ||
}) | ||
@@ -63,8 +76,8 @@ }); | ||
// CREATE - SUCCESS | ||
ensureId(action.payload.item); | ||
var _internalId2 = requireTempId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends4; | ||
return _extends({}, item, action.payload.item, (_extends4 = {}, _defineProperty(_extends4, _fields.fields.error, action.payload.reason), _defineProperty(_extends4, _fields.fields.isCreating, false), _extends4)); | ||
return _extends({}, item, action.payload.item, (_extends4 = {}, _extends4[_fields.fields.error] = action.payload.reason, _extends4[_fields.fields.isCreating] = false, _extends4)); | ||
}) | ||
@@ -76,8 +89,8 @@ }); | ||
// READ | ||
ensureId(action.payload.item); | ||
var _internalId3 = requireId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends5; | ||
return _extends({}, item, action.payload.item, (_extends5 = {}, _defineProperty(_extends5, _fields.fields.error, null), _defineProperty(_extends5, _fields.fields.isReading, false), _extends5)); | ||
return _extends({}, item, action.payload.item, (_extends5 = {}, _extends5[_fields.fields.error] = null, _extends5[_fields.fields.isReading] = false, _extends5)); | ||
}) | ||
@@ -89,8 +102,8 @@ }); | ||
// UPDATE | ||
ensureId(action.payload.item); | ||
var _internalId4 = requireId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends6; | ||
return _extends({}, item, action.payload.item, (_extends6 = {}, _defineProperty(_extends6, _fields.fields.error, null), _defineProperty(_extends6, _fields.fields.isModified, true), _defineProperty(_extends6, _fields.fields.isUpdating, false), _extends6)); | ||
return _extends({}, item, action.payload.item, (_extends6 = {}, _extends6[_fields.fields.error] = null, _extends6[_fields.fields.isModified] = true, _extends6[_fields.fields.isUpdating] = false, _extends6)); | ||
}) | ||
@@ -102,8 +115,8 @@ }); | ||
// UPDATE - CANCEL | ||
ensureId(action.payload.item); | ||
var _internalId5 = requireId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _ref; | ||
return _ref = {}, _defineProperty(_ref, _fields.fields.error, null), _defineProperty(_ref, _fields.fields.isUpdating, false), _ref; | ||
return _ref = {}, _ref[_fields.fields.error] = null, _ref[_fields.fields.isUpdating] = false, _ref; | ||
}) | ||
@@ -115,8 +128,8 @@ }); | ||
// UPDATE - SUCCESS | ||
ensureId(action.payload.item); | ||
var _internalId6 = requireId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends7; | ||
return _extends({}, item, action.payload.item, (_extends7 = {}, _defineProperty(_extends7, _fields.fields.error, null), _defineProperty(_extends7, _fields.fields.isModified, false), _defineProperty(_extends7, _fields.fields.isUpdating, false), _defineProperty(_extends7, _fields.fields.isUpdated, true), _extends7)); | ||
return _extends({}, item, action.payload.item, (_extends7 = {}, _extends7[_fields.fields.error] = null, _extends7[_fields.fields.isModified] = false, _extends7[_fields.fields.isUpdating] = false, _extends7[_fields.fields.isUpdated] = true, _extends7)); | ||
}) | ||
@@ -128,8 +141,8 @@ }); | ||
// UPDATE - FAILURE | ||
ensureId(action.payload.item); | ||
var _internalId7 = requireId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends8; | ||
return _extends({}, item, (_extends8 = {}, _defineProperty(_extends8, _fields.fields.error, action.payload.reason), _defineProperty(_extends8, _fields.fields.isUpdating, false), _extends8)); | ||
return _extends({}, item, (_extends8 = {}, _extends8[_fields.fields.error] = action.payload.reason, _extends8[_fields.fields.isUpdating] = false, _extends8)); | ||
}) | ||
@@ -141,8 +154,8 @@ }); | ||
// DELETE | ||
ensureId(action.payload.item); | ||
var _internalId8 = requireId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends9; | ||
return _extends({}, item, (_extends9 = {}, _defineProperty(_extends9, _fields.fields.error, null), _defineProperty(_extends9, _fields.fields.isModified, true), _defineProperty(_extends9, _fields.fields.isRemoving, true), _extends9)); | ||
return _extends({}, item, (_extends9 = {}, _extends9[_fields.fields.error] = null, _extends9[_fields.fields.isModified] = true, _extends9[_fields.fields.isRemoving] = true, _extends9)); | ||
}) | ||
@@ -154,8 +167,8 @@ }); | ||
// DELETE - CANCEL | ||
ensureId(action.payload.item); | ||
var _internalId9 = requireId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends10; | ||
return _extends({}, item, (_extends10 = {}, _defineProperty(_extends10, _fields.fields.error, null), _defineProperty(_extends10, _fields.fields.isRemoving, false), _extends10)); | ||
return _extends({}, item, (_extends10 = {}, _extends10[_fields.fields.error] = null, _extends10[_fields.fields.isRemoving] = false, _extends10)); | ||
}) | ||
@@ -167,5 +180,5 @@ }); | ||
// DELETE - SUCCESS | ||
ensureId(action.payload.item); | ||
var _internalId10 = requireId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listRemoveById)(state.list, action.payload.item[_fields.fields.id]) | ||
list: (0, _list.listRemove)(descriptor, state.list, action.payload.item) | ||
}); | ||
@@ -176,8 +189,8 @@ } | ||
// DELETE - FAILURE | ||
ensureId(action.payload.item); | ||
var _internalId11 = requireId(action.payload.item); | ||
return _extends({}, state, { | ||
list: (0, _list.listAddOrUpdate)(state.list, action.payload.item[_fields.fields.id], item => { | ||
list: (0, _list.listAddOrUpdate)(descriptor, state.list, action.payload.item, function (item) { | ||
var _extends11; | ||
return _extends({}, item, (_extends11 = {}, _defineProperty(_extends11, _fields.fields.error, action.payload.reason), _defineProperty(_extends11, _fields.fields.isRemoving, false), _extends11)); | ||
return _extends({}, item, (_extends11 = {}, _extends11[_fields.fields.error] = action.payload.reason, _extends11[_fields.fields.isRemoving] = false, _extends11)); | ||
}) | ||
@@ -184,0 +197,0 @@ }); |
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
exports.default = makeSaga; | ||
@@ -15,17 +13,49 @@ | ||
return middlwares.slice(0).reverse().reduce((next, middleware) => { | ||
return function* (action) { | ||
yield* middleware(action, function* () { | ||
let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : action; | ||
return middlwares.slice(0).reverse().reduce(function (next, middleware) { | ||
return regeneratorRuntime.mark(function _callee2(action) { | ||
return regeneratorRuntime.wrap(function _callee2$(_context2) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
return _context2.delegateYield(middleware(action, regeneratorRuntime.mark(function _callee() { | ||
var a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : action; | ||
return regeneratorRuntime.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
return _context.delegateYield(next(a), 't0', 1); | ||
yield* next(a); | ||
}); | ||
}; | ||
}, function* (action) { | ||
console.error('Reached end of middleware.', action); | ||
}); | ||
case 1: | ||
case 'end': | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee, this); | ||
})), 't0', 1); | ||
case 1: | ||
case 'end': | ||
return _context2.stop(); | ||
} | ||
} | ||
}, _callee2, this); | ||
}); | ||
}, regeneratorRuntime.mark(function _callee3(action) { | ||
return regeneratorRuntime.wrap(function _callee3$(_context3) { | ||
while (1) { | ||
switch (_context3.prev = _context3.next) { | ||
case 0: | ||
console.debug('Reached end of middleware.', action); | ||
case 1: | ||
case 'end': | ||
return _context3.stop(); | ||
} | ||
} | ||
}, _callee3, this); | ||
})); | ||
} | ||
function makeSaga(descriptor) { | ||
let actions = [descriptor.actions.CREATE, descriptor.actions.CREATE_CANCEL, descriptor.actions.CREATE_SUCCESS, descriptor.actions.CREATE_FAILURE, descriptor.actions.READ, descriptor.actions.READ_CANCEL, descriptor.actions.READ_SUCCESS, descriptor.actions.READ_FAILURE, descriptor.actions.UPDATE, descriptor.actions.UPDATE_CANCEL, descriptor.actions.UPDATE_SUCCESS, descriptor.actions.UPDATE_FAILURE, descriptor.actions.DELETE, descriptor.actions.DELETE_CANCEL, descriptor.actions.DELETE_SUCCESS, descriptor.actions.DELETE_FAILURE, descriptor.actions.LIST, descriptor.actions.LIST_CANCEL, descriptor.actions.LIST_SUCCESS, descriptor.actions.LIST_FAILURE, descriptor.actions.RESET]; | ||
var actions = [descriptor.actions.CREATE, descriptor.actions.CREATE_CANCEL, descriptor.actions.CREATE_SUCCESS, descriptor.actions.CREATE_FAILURE, descriptor.actions.READ, descriptor.actions.READ_CANCEL, descriptor.actions.READ_SUCCESS, descriptor.actions.READ_FAILURE, descriptor.actions.UPDATE, descriptor.actions.UPDATE_CANCEL, descriptor.actions.UPDATE_SUCCESS, descriptor.actions.UPDATE_FAILURE, descriptor.actions.DELETE, descriptor.actions.DELETE_CANCEL, descriptor.actions.DELETE_SUCCESS, descriptor.actions.DELETE_FAILURE, descriptor.actions.LIST, descriptor.actions.LIST_CANCEL, descriptor.actions.LIST_SUCCESS, descriptor.actions.LIST_FAILURE, descriptor.actions.RESET]; | ||
@@ -36,6 +66,18 @@ for (var _len2 = arguments.length, middlewares = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { | ||
let f = applyMiddlewares(...middlewares); | ||
return function* internal() { | ||
yield (0, _effects.takeEvery)(actions, f); | ||
}; | ||
var f = applyMiddlewares.apply(undefined, middlewares); | ||
return regeneratorRuntime.mark(function internal() { | ||
return regeneratorRuntime.wrap(function internal$(_context4) { | ||
while (1) { | ||
switch (_context4.prev = _context4.next) { | ||
case 0: | ||
_context4.next = 2; | ||
return (0, _effects.takeEvery)(actions, f); | ||
case 2: | ||
case 'end': | ||
return _context4.stop(); | ||
} | ||
} | ||
}, internal, this); | ||
}); | ||
} |
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
exports.default = selectors; | ||
var _ = require('../'); | ||
var _internal = require('../internal'); | ||
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 _fields = require('../fields'); | ||
function selectors(name) { | ||
let scope = state => { | ||
let scope = state[name + 'Resource']; | ||
function selectors(name, options, hasSameId) { | ||
var scope = function scope(state) { | ||
var scope = state[name + 'Resource']; | ||
if (!scope) throw new Error('Register reducer of resource ' + name + ' in the store under: "' + name + 'Resource"'); | ||
@@ -21,8 +17,28 @@ return scope; | ||
return { | ||
loading: state => scope(state).loading, | ||
error: state => scope(state).error, | ||
itemById: (state, id) => scope(state).list.filter(item => (0, _.entityHasSameId)(item, _defineProperty({}, fields.id, id)))[0], | ||
itemByItem: (state, item) => scope(state).list.filter(existing => (0, _.entityHasSameId)(item, existing))[0], | ||
items: state => scope(state).list | ||
loading: function loading(state) { | ||
return scope(state).loading; | ||
}, | ||
error: function error(state) { | ||
return scope(state).error; | ||
}, | ||
itemById: function itemById(id) { | ||
return function (state) { | ||
return scope(state).list.filter(function (item) { | ||
var _hasSameId; | ||
return hasSameId(item, (_hasSameId = {}, _hasSameId[options.id] = id, _hasSameId)); | ||
})[0]; | ||
}; | ||
}, | ||
itemByItem: function itemByItem(item) { | ||
return function (state) { | ||
return scope(state).list.filter(function (existing) { | ||
return hasSameId(item, existing); | ||
})[0]; | ||
}; | ||
}, | ||
items: function items(state) { | ||
return scope(state).list; | ||
} | ||
}; | ||
} |
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
exports.stripFields = exports.selectors = exports.fields = undefined; | ||
@@ -14,5 +12,5 @@ | ||
let fields = exports.fields = { | ||
var fields = exports.fields = { | ||
id: (0, _internal.internal)('id'), | ||
newId: (0, _internal.internal)('newId'), | ||
tempId: (0, _internal.internal)('tempId'), | ||
error: (0, _internal.internal)('error'), | ||
@@ -30,24 +28,60 @@ isModified: (0, _internal.internal)('isModified'), | ||
let selectors = exports.selectors = { | ||
id: item => item[fields.id], | ||
newId: item => item[fields.newId], | ||
error: item => item[fields.error], | ||
isModified: item => item[fields.isModified], | ||
isReading: item => item[fields.isReading], | ||
isRead: item => item[fields.isRead], | ||
isCreating: item => item[fields.isCreating], | ||
isCreated: item => item[fields.isCreated], | ||
isRemoving: item => item[fields.isRemoving], | ||
isRemoved: item => item[fields.isRemoved], | ||
isUpdating: item => item[fields.isUpdating], | ||
isUpdated: item => item[fields.isUpdated], | ||
isUnchanged: item => !item[fields.isReading] && !item[fields.isCreating] && !item[fields.isRemoving] && !item[fields.isUpdating], | ||
isChanging: item => item[fields.isReading] || item[fields.isCreating] || item[fields.isRemoving] || item[fields.isUpdating], | ||
neverCommited: item => !item[fields.isRead] && !item[fields.isCreated] && !item[fields.isRemoved] && !item[fields.isUpdated], | ||
hasCommited: item => item[fields.isRead] || item[fields.isCreated] || item[fields.isRemoved] || item[fields.isUpdated] | ||
var selectors = exports.selectors = { | ||
key: function key(item) { | ||
return item[fields.id] || item[fields.tempId]; | ||
}, | ||
id: function id(item) { | ||
return item[fields.id]; | ||
}, | ||
tempId: function tempId(item) { | ||
return item[fields.tempId]; | ||
}, | ||
error: function error(item) { | ||
return item[fields.error]; | ||
}, | ||
isModified: function isModified(item) { | ||
return item[fields.isModified]; | ||
}, | ||
isReading: function isReading(item) { | ||
return item[fields.isReading]; | ||
}, | ||
isRead: function isRead(item) { | ||
return item[fields.isRead]; | ||
}, | ||
isCreating: function isCreating(item) { | ||
return item[fields.isCreating]; | ||
}, | ||
isCreated: function isCreated(item) { | ||
return item[fields.isCreated]; | ||
}, | ||
isRemoving: function isRemoving(item) { | ||
return item[fields.isRemoving]; | ||
}, | ||
isRemoved: function isRemoved(item) { | ||
return item[fields.isRemoved]; | ||
}, | ||
isUpdating: function isUpdating(item) { | ||
return item[fields.isUpdating]; | ||
}, | ||
isUpdated: function isUpdated(item) { | ||
return item[fields.isUpdated]; | ||
}, | ||
isUnchanged: function isUnchanged(item) { | ||
return !item[fields.isReading] && !item[fields.isCreating] && !item[fields.isRemoving] && !item[fields.isUpdating]; | ||
}, | ||
isChanging: function isChanging(item) { | ||
return item[fields.isReading] || item[fields.isCreating] || item[fields.isRemoving] || item[fields.isUpdating]; | ||
}, | ||
neverCommited: function neverCommited(item) { | ||
return !item[fields.isRead] && !item[fields.isCreated] && !item[fields.isRemoved] && !item[fields.isUpdated]; | ||
}, | ||
hasCommited: function hasCommited(item) { | ||
return item[fields.isRead] || item[fields.isCreated] || item[fields.isRemoved] || item[fields.isUpdated]; | ||
} | ||
}; | ||
let stripFields = obj => { | ||
let id = obj[fields.id], | ||
newId = obj[fields.newId], | ||
var stripFields = function stripFields(obj) { | ||
var id = obj[fields.id], | ||
tempId = obj[fields.tempId], | ||
error = obj[fields.error], | ||
isModified = obj[fields.isModified], | ||
@@ -62,7 +96,7 @@ isReading = obj[fields.isReading], | ||
isUpdated = obj[fields.isUpdated], | ||
remainder = _objectWithoutProperties(obj, [fields.id, fields.newId, fields.isModified, fields.isReading, fields.isRead, fields.isCreating, fields.isCreated, fields.isRemoving, fields.isRemoved, fields.isUpdating, fields.isUpdated]); | ||
remainder = _objectWithoutProperties(obj, [fields.id, fields.tempId, fields.error, fields.isModified, fields.isReading, fields.isRead, fields.isCreating, fields.isCreated, fields.isRemoving, fields.isRemoved, fields.isUpdating, fields.isUpdated]); | ||
let cleaned = _extends({ id: id }, remainder); | ||
var cleaned = _extends({}, remainder); | ||
return cleaned; | ||
}; | ||
exports.stripFields = stripFields; |
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
exports.httpMiddleware = undefined; | ||
@@ -13,9 +11,9 @@ | ||
Object.defineProperty(exports, 'httpMiddleware', { | ||
enumerable: true, | ||
get: function get() { | ||
return _http.httpMiddleware; | ||
} | ||
enumerable: true, | ||
get: function get() { | ||
return _http.httpMiddleware; | ||
} | ||
}); | ||
exports.createResource = createResource; | ||
exports.entityHasSameId = entityHasSameId; | ||
exports.createEditor = createEditor; | ||
@@ -40,2 +38,6 @@ var _effects = require('redux-saga/effects'); | ||
var _dataSelectors = require('./factories/dataSelectors'); | ||
var _dataSelectors2 = _interopRequireDefault(_dataSelectors); | ||
var _reducer = require('./factories/reducer'); | ||
@@ -53,39 +55,112 @@ | ||
var _actions3 = require('./editor/actions'); | ||
var _actions4 = _interopRequireDefault(_actions3); | ||
var _creators3 = require('./editor/creators'); | ||
var _creators4 = _interopRequireDefault(_creators3); | ||
var _selectors3 = require('./editor/selectors'); | ||
var _selectors4 = _interopRequireDefault(_selectors3); | ||
var _reducer3 = require('./editor/reducer'); | ||
var _reducer4 = _interopRequireDefault(_reducer3); | ||
var _saga3 = require('./editor/saga'); | ||
var _saga4 = _interopRequireDefault(_saga3); | ||
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; } | ||
function createResource(name, options) { | ||
options = _extends({ | ||
id: 'id' | ||
}, options); | ||
options = _extends({ | ||
id: 'id' | ||
}, options); | ||
let descriptor = { | ||
name: name, | ||
options: options, | ||
actions: (0, _actions2.default)(name), | ||
creators: (0, _creators2.default)(name, (0, _actions2.default)(name)), | ||
selectors: (0, _selectors2.default)(name), | ||
fields: _fields.selectors | ||
}; | ||
var descriptor = { | ||
name: name, | ||
data: (0, _dataSelectors2.default)(options), | ||
options: options, | ||
actions: (0, _actions2.default)(name), | ||
creators: (0, _creators2.default)(name, (0, _actions2.default)(name)), | ||
selectors: (0, _selectors2.default)(name, options, entityHasSameId(options)), | ||
fields: _fields.selectors, | ||
hasSameId: entityHasSameId(options) | ||
}; | ||
for (var _len = arguments.length, middlewares = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
middlewares[_key - 2] = arguments[_key]; | ||
} | ||
for (var _len = arguments.length, middlewares = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
middlewares[_key - 2] = arguments[_key]; | ||
} | ||
return _extends({}, descriptor, { | ||
create: props => { | ||
var _extends2; | ||
return _extends({}, descriptor, { | ||
create: function create(props) { | ||
var _extends2; | ||
return _extends({}, props, (_extends2 = {}, _defineProperty(_extends2, _fields.fields.id, (0, _tempKey.makeTempKey)()), _defineProperty(_extends2, _fields.fields.status, status.UNSURE), _extends2)); | ||
}, | ||
reducer: (0, _reducer2.default)(descriptor), | ||
saga: (0, _saga2.default)(descriptor, ...middlewares.map(f => f(descriptor))) | ||
}); | ||
return _extends({}, props, (_extends2 = {}, _extends2[_fields.fields.tempId] = (0, _tempKey.makeTempKey)(), _extends2)); | ||
}, | ||
reducer: (0, _reducer2.default)(descriptor), | ||
saga: _saga2.default.apply(undefined, [descriptor].concat(middlewares.map(function (f) { | ||
return f(descriptor); | ||
}))) | ||
}); | ||
} | ||
function entityHasSameId(left, right) { | ||
function createEditor(name, options, resource) { | ||
options = _extends({ | ||
id: 'id' | ||
}, options); | ||
var descriptor = { | ||
resource: resource, | ||
name: name, | ||
options: options, | ||
actions: (0, _actions4.default)(name), | ||
creators: (0, _creators4.default)(name, (0, _actions4.default)(name)), | ||
selectors: (0, _selectors4.default)(name, options, resource) | ||
}; | ||
for (var _len2 = arguments.length, middlewares = Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) { | ||
middlewares[_key2 - 3] = arguments[_key2]; | ||
} | ||
return _extends({}, descriptor, { | ||
reducer: (0, _reducer4.default)(descriptor), | ||
saga: _saga4.default.apply(undefined, [descriptor].concat(middlewares.map(function (f) { | ||
return f(descriptor); | ||
}))) | ||
}); | ||
} | ||
function entityHasSameId(options) { | ||
var internalId = _fields.fields.id, | ||
tempId = _fields.fields.tempId; | ||
var id = options.id; | ||
var leftId, rightId; | ||
return function (left, right) { | ||
if (left === right) return true; | ||
if (!left || !right) return false; | ||
return left[_fields.fields.id] === right[_fields.fields.id]; | ||
if (left && right) { | ||
// Internal ID | ||
leftId = left[internalId]; | ||
rightId = right[internalId]; | ||
if (leftId && leftId === rightId) return true; | ||
// Object ID | ||
if (id) { | ||
leftId = left[id]; | ||
rightId = right[id]; | ||
if (leftId && leftId === rightId) return true; | ||
} | ||
// Temporary ID | ||
leftId = left[tempId]; | ||
rightId = right[tempId]; | ||
if (leftId && leftId === rightId) return true; | ||
} | ||
return false; | ||
}; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
let internal = exports.internal = id => "@@saga-resources/" + id; | ||
let isInternal = exports.isInternal = id => /^@@saga-resources\//.test(id); | ||
exports.__esModule = true; | ||
var internal = exports.internal = function internal(id) { | ||
return "@@saga-resources/" + id; | ||
}; | ||
var isInternal = exports.isInternal = function isInternal(id) { | ||
return (/^@@saga-resources\//.test(id) | ||
); | ||
}; |
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
@@ -19,24 +17,36 @@ 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; }; | ||
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 configTimeout = 8000; | ||
let configTimeout = 8000; | ||
function httpMiddleware(api, path) { | ||
return descriptor => { | ||
return function (descriptor) { | ||
var _mapping; | ||
let fnCreate = sagaCreate(api, path, descriptor); | ||
let fnRead = sagaRead(api, path, descriptor); | ||
let fnUpdate = sagaUpdate(api, path, descriptor); | ||
let fnDelete = sagaDelete(api, path, descriptor); | ||
let fnList = sagaList(api, path, descriptor); | ||
let fnReset = sagaReset(api, path, descriptor); | ||
var fnCreate = sagaCreate(api, path, descriptor); | ||
var fnRead = sagaRead(api, path, descriptor); | ||
var fnUpdate = sagaUpdate(api, path, descriptor); | ||
var fnDelete = sagaDelete(api, path, descriptor); | ||
var fnList = sagaList(api, path, descriptor); | ||
var fnReset = sagaReset(api, path, descriptor); | ||
let mapping = (_mapping = {}, _defineProperty(_mapping, descriptor.actions.CREATE, fnCreate), _defineProperty(_mapping, descriptor.actions.READ, fnRead), _defineProperty(_mapping, descriptor.actions.UPDATE, fnUpdate), _defineProperty(_mapping, descriptor.actions.DELETE, fnDelete), _defineProperty(_mapping, descriptor.actions.LIST, fnList), _defineProperty(_mapping, descriptor.actions.RESET, fnReset), _mapping); | ||
var mapping = (_mapping = {}, _mapping[descriptor.actions.CREATE] = fnCreate, _mapping[descriptor.actions.READ] = fnRead, _mapping[descriptor.actions.UPDATE] = fnUpdate, _mapping[descriptor.actions.DELETE] = fnDelete, _mapping[descriptor.actions.LIST] = fnList, _mapping[descriptor.actions.RESET] = fnReset, _mapping); | ||
return function* (action, next) { | ||
if (action.type in mapping) { | ||
yield* mapping[action.type](next)(action); | ||
} | ||
}; | ||
return regeneratorRuntime.mark(function _callee(action, next) { | ||
return regeneratorRuntime.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
if (!(action.type in mapping)) { | ||
_context.next = 2; | ||
break; | ||
} | ||
return _context.delegateYield(mapping[action.type](next)(action), 't0', 2); | ||
case 2: | ||
case 'end': | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee, this); | ||
}); | ||
}; | ||
@@ -46,35 +56,72 @@ } | ||
function sagaCreate(api, path, descriptor) { | ||
return next => function* (action) { | ||
let key = action.payload.item[_fields.fields.id]; | ||
return function (next) { | ||
return regeneratorRuntime.mark(function _callee2(action) { | ||
var tempId, _stripFields, id, item, _ref, res, cancel, _extends2, data; | ||
var _stripFields = (0, _fields.stripFields)(action.payload.item); | ||
return regeneratorRuntime.wrap(function _callee2$(_context2) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
tempId = action.payload.item[_fields.fields.tempId]; | ||
_stripFields = (0, _fields.stripFields)(action.payload.item), id = _stripFields.id, item = _objectWithoutProperties(_stripFields, ['id']); | ||
_context2.next = 4; | ||
return (0, _effects.race)({ | ||
res: api.post('' + path, item), | ||
cancel: (0, _effects.take)([descriptor.actions.CREATE_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
let id = _stripFields.id, | ||
item = _objectWithoutProperties(_stripFields, ['id']); | ||
case 4: | ||
_ref = _context2.sent; | ||
res = _ref.res; | ||
cancel = _ref.cancel; | ||
var _ref = yield (0, _effects.race)({ | ||
res: api.post('' + path, item), | ||
cancel: (0, _effects.take)([descriptor.actions.CREATE_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
if (!(res && res.ok)) { | ||
_context2.next = 16; | ||
break; | ||
} | ||
let res = _ref.res, | ||
cancel = _ref.cancel; | ||
_context2.next = 10; | ||
return (0, _effects.call)(function () { | ||
return res.json(); | ||
}); | ||
case 10: | ||
data = _context2.sent; | ||
_context2.next = 13; | ||
return (0, _effects.put)(descriptor.creators.doCreateSuccess(_extends({}, action.payload.item, data, (_extends2 = {}, _extends2[_fields.fields.id] = descriptor.data.id(data), _extends2)))); | ||
if (res && res.ok) { | ||
var _extends2; | ||
case 13: | ||
return _context2.delegateYield(next(), 't0', 14); | ||
// Success. | ||
let data = yield (0, _effects.call)(() => res.json()); | ||
yield (0, _effects.put)(descriptor.creators.doCreateSuccess(_extends((_extends2 = {}, _defineProperty(_extends2, _fields.fields.id, key), _defineProperty(_extends2, _fields.fields.newId, data.id), _extends2), data))); | ||
yield* next(); | ||
} else if (cancel) { | ||
// Cancelled. | ||
yield* next(); | ||
} else { | ||
// Error. | ||
yield (0, _effects.put)(descriptor.creators.doCreateFailure(_extends({}, action.payload.item), res.status + ' ' + res.statusText)); | ||
yield* next(); | ||
} | ||
case 14: | ||
_context2.next = 23; | ||
break; | ||
case 16: | ||
if (!cancel) { | ||
_context2.next = 20; | ||
break; | ||
} | ||
return _context2.delegateYield(next(), 't1', 18); | ||
case 18: | ||
_context2.next = 23; | ||
break; | ||
case 20: | ||
_context2.next = 22; | ||
return (0, _effects.put)(descriptor.creators.doCreateFailure(_extends({}, action.payload.item), res.status + ' ' + res.statusText)); | ||
case 22: | ||
return _context2.delegateYield(next(), 't2', 23); | ||
case 23: | ||
case 'end': | ||
return _context2.stop(); | ||
} | ||
} | ||
}, _callee2, this); | ||
}); | ||
}; | ||
@@ -84,29 +131,72 @@ } | ||
function sagaRead(api, path, descriptor) { | ||
return next => function* (action) { | ||
let key = action.payload.item[_fields.fields.id]; | ||
let item = (0, _fields.stripFields)(action.payload.item); | ||
return function (next) { | ||
return regeneratorRuntime.mark(function _callee3(action) { | ||
var key, item, _ref2, res, cancel, _extends3, data; | ||
var _ref2 = yield (0, _effects.race)({ | ||
res: api.get(path + '/' + key, item), | ||
cancel: (0, _effects.take)([descriptor.actions.READ_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
return regeneratorRuntime.wrap(function _callee3$(_context3) { | ||
while (1) { | ||
switch (_context3.prev = _context3.next) { | ||
case 0: | ||
key = descriptor.data.id(action.payload.item); | ||
item = (0, _fields.stripFields)(action.payload.item); | ||
_context3.next = 4; | ||
return (0, _effects.race)({ | ||
res: api.get(path + '/' + key, item), | ||
cancel: (0, _effects.take)([descriptor.actions.READ_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
let res = _ref2.res, | ||
cancel = _ref2.cancel; | ||
case 4: | ||
_ref2 = _context3.sent; | ||
res = _ref2.res; | ||
cancel = _ref2.cancel; | ||
if (!(res && res.ok)) { | ||
_context3.next = 16; | ||
break; | ||
} | ||
if (res && res.ok) { | ||
// Success. | ||
let data = yield (0, _effects.call)(() => res.json()); | ||
yield (0, _effects.put)(descriptor.creators.doReadSuccess(_extends(_defineProperty({}, _fields.fields.id, key), data))); | ||
yield* next(); | ||
} else if (cancel) { | ||
// Cancelled. | ||
yield* next(); | ||
} else { | ||
// Error. | ||
yield (0, _effects.put)(descriptor.creators.doReadFailure(action.payload.item, res.status + ' ' + res.statusText)); | ||
yield* next(); | ||
} | ||
_context3.next = 10; | ||
return (0, _effects.call)(function () { | ||
return res.json(); | ||
}); | ||
case 10: | ||
data = _context3.sent; | ||
_context3.next = 13; | ||
return (0, _effects.put)(descriptor.creators.doReadSuccess(_extends({}, action.payload.item, data, (_extends3 = {}, _extends3[_fields.fields.id] = key, _extends3)))); | ||
case 13: | ||
return _context3.delegateYield(next(), 't0', 14); | ||
case 14: | ||
_context3.next = 23; | ||
break; | ||
case 16: | ||
if (!cancel) { | ||
_context3.next = 20; | ||
break; | ||
} | ||
return _context3.delegateYield(next(), 't1', 18); | ||
case 18: | ||
_context3.next = 23; | ||
break; | ||
case 20: | ||
_context3.next = 22; | ||
return (0, _effects.put)(descriptor.creators.doReadFailure(action.payload.item, res.status + ' ' + res.statusText)); | ||
case 22: | ||
return _context3.delegateYield(next(), 't2', 23); | ||
case 23: | ||
case 'end': | ||
return _context3.stop(); | ||
} | ||
} | ||
}, _callee3, this); | ||
}); | ||
}; | ||
@@ -116,35 +206,74 @@ } | ||
function sagaUpdate(api, path, descriptor) { | ||
return next => function* (action) { | ||
let key = action.payload.item[_fields.fields.id]; | ||
return function (next) { | ||
return regeneratorRuntime.mark(function _callee4(action) { | ||
var key, _stripFields2, id, item, _ref3, res, cancel, _extends4, data; | ||
var _stripFields2 = (0, _fields.stripFields)(action.payload.item); | ||
return regeneratorRuntime.wrap(function _callee4$(_context4) { | ||
while (1) { | ||
switch (_context4.prev = _context4.next) { | ||
case 0: | ||
key = descriptor.data.id(action.payload.item); | ||
_stripFields2 = (0, _fields.stripFields)(action.payload.item), id = _stripFields2.id, item = _objectWithoutProperties(_stripFields2, ['id']); | ||
_context4.next = 4; | ||
return (0, _effects.race)({ | ||
res: api.patch(path + '/' + key, _extends({}, item, { | ||
id: key | ||
})), | ||
cancel: (0, _effects.take)([descriptor.actions.UPDATE_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
let id = _stripFields2.id, | ||
item = _objectWithoutProperties(_stripFields2, ['id']); | ||
case 4: | ||
_ref3 = _context4.sent; | ||
res = _ref3.res; | ||
cancel = _ref3.cancel; | ||
var _ref3 = yield (0, _effects.race)({ | ||
res: api.patch(path + '/' + key, _extends({}, item, { id: key })), | ||
cancel: (0, _effects.take)([descriptor.actions.UPDATE_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
if (!(res && res.ok)) { | ||
_context4.next = 16; | ||
break; | ||
} | ||
let res = _ref3.res, | ||
cancel = _ref3.cancel; | ||
_context4.next = 10; | ||
return (0, _effects.call)(function () { | ||
return res.json(); | ||
}); | ||
case 10: | ||
data = _context4.sent; | ||
_context4.next = 13; | ||
return (0, _effects.put)(descriptor.creators.doUpdateSuccess(_extends({}, action.payload.item, data, (_extends4 = {}, _extends4[_fields.fields.id] = data.id, _extends4)))); | ||
if (res && res.ok) { | ||
var _extends4; | ||
case 13: | ||
return _context4.delegateYield(next(), 't0', 14); | ||
// Success. | ||
let data = yield (0, _effects.call)(() => res.json()); | ||
yield (0, _effects.put)(descriptor.creators.doUpdateSuccess(_extends((_extends4 = {}, _defineProperty(_extends4, _fields.fields.id, key), _defineProperty(_extends4, _fields.fields.newId, data.id), _extends4), data))); | ||
yield* next(); | ||
} else if (cancel) { | ||
// Cancelled. | ||
yield* next(); | ||
} else { | ||
// Error. | ||
yield (0, _effects.put)(descriptor.creators.doUpdateFailure(_extends({}, action.payload.item), res.status + ' ' + res.statusText)); | ||
yield* next(); | ||
} | ||
case 14: | ||
_context4.next = 23; | ||
break; | ||
case 16: | ||
if (!cancel) { | ||
_context4.next = 20; | ||
break; | ||
} | ||
return _context4.delegateYield(next(), 't1', 18); | ||
case 18: | ||
_context4.next = 23; | ||
break; | ||
case 20: | ||
_context4.next = 22; | ||
return (0, _effects.put)(descriptor.creators.doUpdateFailure(_extends({}, action.payload.item), res.status + ' ' + res.statusText)); | ||
case 22: | ||
return _context4.delegateYield(next(), 't2', 23); | ||
case 23: | ||
case 'end': | ||
return _context4.stop(); | ||
} | ||
} | ||
}, _callee4, this); | ||
}); | ||
}; | ||
@@ -154,34 +283,80 @@ } | ||
function sagaDelete(api, path, descriptor) { | ||
return next => function* (action) { | ||
if (descriptor.fields.neverCommited(action.payload.item)) { | ||
yield (0, _effects.put)(descriptor.creators.doDeleteSuccess(action.payload.item)); | ||
yield* next(); | ||
return; | ||
} | ||
return function (next) { | ||
return regeneratorRuntime.mark(function _callee5(action) { | ||
var key, item, _ref4, res, cancel; | ||
let key = action.payload.item[_fields.fields.id]; | ||
let item = (0, _fields.stripFields)(action.payload.item); | ||
return regeneratorRuntime.wrap(function _callee5$(_context5) { | ||
while (1) { | ||
switch (_context5.prev = _context5.next) { | ||
case 0: | ||
if (!descriptor.fields.neverCommited(action.payload.item)) { | ||
_context5.next = 5; | ||
break; | ||
} | ||
var _ref4 = yield (0, _effects.race)({ | ||
res: api.del(path + '/' + key, item), | ||
cancel: (0, _effects.take)([descriptor.actions.DELETE_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
_context5.next = 3; | ||
return (0, _effects.put)(descriptor.creators.doDeleteSuccess(action.payload.item)); | ||
let res = _ref4.res, | ||
cancel = _ref4.cancel; | ||
case 3: | ||
return _context5.delegateYield(next(), 't0', 4); | ||
case 4: | ||
return _context5.abrupt('return'); | ||
if (res && res.ok || res.status === 404) { | ||
// Success, or non existing. | ||
yield (0, _effects.put)(descriptor.creators.doDeleteSuccess(action.payload.item)); | ||
yield* next(); | ||
} else if (cancel) { | ||
// Cancelled. | ||
yield* next(); | ||
} else { | ||
// Error. | ||
yield (0, _effects.put)(descriptor.creators.doDeleteFailure(action.payload.item, res.status + ' ' + res.statusText)); | ||
yield* next(); | ||
} | ||
case 5: | ||
key = descriptor.data.id(action.payload.item); | ||
item = (0, _fields.stripFields)(action.payload.item); | ||
_context5.next = 9; | ||
return (0, _effects.race)({ | ||
res: api.del(path + '/' + key, item), | ||
cancel: (0, _effects.take)([descriptor.actions.DELETE_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
case 9: | ||
_ref4 = _context5.sent; | ||
res = _ref4.res; | ||
cancel = _ref4.cancel; | ||
if (!(res && res.ok || res.status === 404)) { | ||
_context5.next = 18; | ||
break; | ||
} | ||
_context5.next = 15; | ||
return (0, _effects.put)(descriptor.creators.doDeleteSuccess(action.payload.item)); | ||
case 15: | ||
return _context5.delegateYield(next(), 't1', 16); | ||
case 16: | ||
_context5.next = 25; | ||
break; | ||
case 18: | ||
if (!cancel) { | ||
_context5.next = 22; | ||
break; | ||
} | ||
return _context5.delegateYield(next(), 't2', 20); | ||
case 20: | ||
_context5.next = 25; | ||
break; | ||
case 22: | ||
_context5.next = 24; | ||
return (0, _effects.put)(descriptor.creators.doDeleteFailure(action.payload.item, res.status + ' ' + res.statusText)); | ||
case 24: | ||
return _context5.delegateYield(next(), 't3', 25); | ||
case 25: | ||
case 'end': | ||
return _context5.stop(); | ||
} | ||
} | ||
}, _callee5, this); | ||
}); | ||
}; | ||
@@ -191,32 +366,74 @@ } | ||
function sagaList(api, path, descriptor) { | ||
return next => function* (action) { | ||
console.log('LIST ' + path, action); | ||
return function (next) { | ||
return regeneratorRuntime.mark(function _callee6(action) { | ||
var _ref5, res, cancel, data; | ||
var _ref5 = yield (0, _effects.race)({ | ||
res: api.get('' + path), | ||
cancel: (0, _effects.take)([descriptor.actions.LIST_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
return regeneratorRuntime.wrap(function _callee6$(_context6) { | ||
while (1) { | ||
switch (_context6.prev = _context6.next) { | ||
case 0: | ||
_context6.next = 2; | ||
return (0, _effects.race)({ | ||
res: api.get('' + path), | ||
cancel: (0, _effects.take)([descriptor.actions.LIST_CANCEL, descriptor.actions.RESET]), | ||
timeout: (0, _effects.call)(_reduxSaga.delay, configTimeout) | ||
}); | ||
let res = _ref5.res, | ||
cancel = _ref5.cancel; | ||
case 2: | ||
_ref5 = _context6.sent; | ||
res = _ref5.res; | ||
cancel = _ref5.cancel; | ||
if (!(res && res.ok)) { | ||
_context6.next = 14; | ||
break; | ||
} | ||
if (res && res.ok) { | ||
// Success. | ||
let data = yield (0, _effects.call)(() => res.json()); | ||
yield (0, _effects.put)(descriptor.creators.doListSuccess(data.map(item => { | ||
var _extends5; | ||
_context6.next = 8; | ||
return (0, _effects.call)(function () { | ||
return res.json(); | ||
}); | ||
return _extends((_extends5 = {}, _defineProperty(_extends5, _fields.fields.id, item.id), _defineProperty(_extends5, _fields.fields.isRead, true), _extends5), item); | ||
}))); | ||
yield* next(); | ||
} else if (cancel) { | ||
// Cancelled. | ||
yield* next(); | ||
} else { | ||
// Error. | ||
yield (0, _effects.put)(descriptor.creators.doListFailure(res.status + ' ' + res.statusText)); | ||
yield* next(); | ||
} | ||
case 8: | ||
data = _context6.sent; | ||
_context6.next = 11; | ||
return (0, _effects.put)(descriptor.creators.doListSuccess(data.map(function (item) { | ||
var _extends5; | ||
return _extends((_extends5 = {}, _extends5[_fields.fields.id] = descriptor.data.id(item), _extends5[_fields.fields.isRead] = true, _extends5), item); | ||
}))); | ||
case 11: | ||
return _context6.delegateYield(next(), 't0', 12); | ||
case 12: | ||
_context6.next = 21; | ||
break; | ||
case 14: | ||
if (!cancel) { | ||
_context6.next = 18; | ||
break; | ||
} | ||
return _context6.delegateYield(next(), 't1', 16); | ||
case 16: | ||
_context6.next = 21; | ||
break; | ||
case 18: | ||
_context6.next = 20; | ||
return (0, _effects.put)(descriptor.creators.doListFailure(res.status + ' ' + res.statusText)); | ||
case 20: | ||
return _context6.delegateYield(next(), 't2', 21); | ||
case 21: | ||
case 'end': | ||
return _context6.stop(); | ||
} | ||
} | ||
}, _callee6, this); | ||
}); | ||
}; | ||
@@ -226,5 +443,18 @@ } | ||
function sagaReset(api, path, descriptor) { | ||
return next => function* (action) { | ||
yield* next(); | ||
return function (next) { | ||
return regeneratorRuntime.mark(function _callee7(action) { | ||
return regeneratorRuntime.wrap(function _callee7$(_context7) { | ||
while (1) { | ||
switch (_context7.prev = _context7.next) { | ||
case 0: | ||
return _context7.delegateYield(next(), 't0', 1); | ||
case 1: | ||
case 'end': | ||
return _context7.stop(); | ||
} | ||
} | ||
}, _callee7, this); | ||
}); | ||
}; | ||
} |
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
exports.isTempKey = exports.makeTempKey = undefined; | ||
@@ -11,3 +9,7 @@ | ||
var tempKeyCounter = 0; | ||
let makeTempKey = exports.makeTempKey = () => (0, _internal.internal)(Date.now() + '_' + ++tempKeyCounter + '_TEMP'); | ||
let isTempKey = exports.isTempKey = key => (0, _internal.isInternal)(key) && /_TEMP$/.test(key); | ||
var makeTempKey = exports.makeTempKey = function makeTempKey() { | ||
return (0, _internal.internal)(Date.now() + '_' + ++tempKeyCounter + '_TEMP'); | ||
}; | ||
var isTempKey = exports.isTempKey = function isTempKey(key) { | ||
return (0, _internal.isInternal)(key) && /_TEMP$/.test(key); | ||
}; |
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__esModule = true; | ||
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.listAddOrUpdate = listAddOrUpdate; | ||
exports.listRemoveById = listRemoveById; | ||
exports.listRemove = listRemove; | ||
var _fields = require('../fields'); | ||
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; } | ||
function listAddOrUpdate(descriptor, list, bareItem, transform) { | ||
var hasSameId = descriptor.hasSameId; | ||
function listAddOrUpdate(list, id, transform) { | ||
var count = 0; | ||
let res = list.map(item => { | ||
if (item[_fields.fields.id] !== id) { | ||
var res = list.map(function (item) { | ||
if (!hasSameId(item, bareItem)) { | ||
return item; | ||
@@ -21,9 +22,8 @@ } | ||
++count; | ||
return transform(item); | ||
var res = transform(item); | ||
return res; | ||
}); | ||
if (count === 0) { | ||
var _transform; | ||
// Add new. | ||
res.push(transform((_transform = {}, _defineProperty(_transform, _fields.fields.id, id), _defineProperty(_transform, _fields.fields.status, status.UNKNOWN), _transform))); | ||
res.push(transform(_extends({}, bareItem))); | ||
} | ||
@@ -33,4 +33,6 @@ return res; | ||
function listRemoveById(list, id) { | ||
return list.filter(item => item[_fields.fields.id] !== id); | ||
function listRemove(descriptor, list, bareItem) { | ||
return list.filter(function (item) { | ||
return !descriptor.hasSameId(item, bareItem); | ||
}); | ||
} |
265
index.d.ts
declare module "redux-saga-resources" { | ||
interface IActions { | ||
CREATE: string; | ||
CREATE_CANCEL: string; | ||
CREATE_SUCCESS: string; | ||
CREATE_FAILURE: string; | ||
interface IActions { | ||
CREATE: string; | ||
CREATE_CANCEL: string; | ||
CREATE_SUCCESS: string; | ||
CREATE_FAILURE: string; | ||
READ: string; | ||
READ_CANCEL: string; | ||
READ_SUCCESS: string; | ||
READ_FAILURE: string; | ||
READ: string; | ||
READ_CANCEL: string; | ||
READ_SUCCESS: string; | ||
READ_FAILURE: string; | ||
UPDATE: string; | ||
UPDATE_CANCEL: string; | ||
UPDATE_SUCCESS: string; | ||
UPDATE_FAILURE: string; | ||
UPDATE: string; | ||
UPDATE_CANCEL: string; | ||
UPDATE_SUCCESS: string; | ||
UPDATE_FAILURE: string; | ||
DELETE: string; | ||
DELETE_CANCEL: string; | ||
DELETE_SUCCESS: string; | ||
DELETE_FAILURE: string; | ||
DELETE: string; | ||
DELETE_CANCEL: string; | ||
DELETE_SUCCESS: string; | ||
DELETE_FAILURE: string; | ||
LIST: string; | ||
LIST_CANCEL: string; | ||
LIST_SUCCESS: string; | ||
LIST_FAILURE: string; | ||
LIST: string; | ||
LIST_CANCEL: string; | ||
LIST_SUCCESS: string; | ||
LIST_FAILURE: string; | ||
RESET: string; | ||
} | ||
RESET: string; | ||
} | ||
interface ICreators { | ||
doCreate(item): any; | ||
doCreateCancel(item): any; | ||
doCreateSuccess(item): any; | ||
doCreateFailure(item, reason): any; | ||
interface ICreators { | ||
doCreate(item): any; | ||
doCreateCancel(item): any; | ||
doCreateSuccess(item): any; | ||
doCreateFailure(item, reason): any; | ||
doRead(item): any; | ||
doReadCancel(item): any; | ||
doReadSuccess(item): any; | ||
doReadFailure(item, reason): any; | ||
doRead(item): any; | ||
doReadCancel(item): any; | ||
doReadSuccess(item): any; | ||
doReadFailure(item, reason): any; | ||
doUpdate(item): any; | ||
doUpdateCancel(item): any; | ||
doUpdateSuccess(item): any; | ||
doUpdateFailure(item, reason): any; | ||
doUpdate(item): any; | ||
doUpdateCancel(item): any; | ||
doUpdateSuccess(item): any; | ||
doUpdateFailure(item, reason): any; | ||
doDelete(item): any; | ||
doDeleteCancel(item): any; | ||
doDeleteSuccess(item): any; | ||
doDeleteFailure(item, reason): any; | ||
doDelete(item): any; | ||
doDeleteCancel(item): any; | ||
doDeleteSuccess(item): any; | ||
doDeleteFailure(item, reason): any; | ||
doList(): any; | ||
doListCancel(): any; | ||
doListSuccess(): any; | ||
doListFailure(reason): any; | ||
doList(): any; | ||
doListCancel(): any; | ||
doListSuccess(): any; | ||
doListFailure(reason): any; | ||
doReset(): any; | ||
} | ||
doReset(): any; | ||
} | ||
interface ISelectors { | ||
loading(state): boolean; | ||
error(state): any; | ||
items(state): any[]; | ||
itemById(state, id): any; | ||
itemByItem(state, item): any; | ||
} | ||
interface ISelectors { | ||
loading(state): boolean; | ||
error(state): string; | ||
items(state): any[]; | ||
itemById(state, id): any; | ||
itemByItem(state, item): any; | ||
} | ||
interface IFieldSelectors { | ||
id(item): string; | ||
status(item): boolean; | ||
error(item): any; | ||
isModified(item): boolean; | ||
isReading(item): boolean; | ||
isRead(item): boolean; | ||
isCreating(item): boolean; | ||
isCreated(item): boolean; | ||
isRemoving(item): boolean; | ||
isRemoved(item): boolean; | ||
isUpdating(item): boolean; | ||
isUpdated(item): boolean; | ||
isUnchanged(item): boolean; | ||
isChanging(item): boolean; | ||
neverCommited(item): boolean; | ||
hasCommited(item): boolean; | ||
} | ||
interface IFieldSelectors { | ||
key(item): string; | ||
id(item): string; | ||
newId(item): string; | ||
status(item): boolean; | ||
error(item): any; | ||
isModified(item): boolean; | ||
isReading(item): boolean; | ||
isRead(item): boolean; | ||
isCreating(item): boolean; | ||
isCreated(item): boolean; | ||
isRemoving(item): boolean; | ||
isRemoved(item): boolean; | ||
isUpdating(item): boolean; | ||
isUpdated(item): boolean; | ||
isUnchanged(item): boolean; | ||
isChanging(item): boolean; | ||
neverCommited(item): boolean; | ||
hasCommited(item): boolean; | ||
} | ||
interface IResourceDescriptor { | ||
name: string; | ||
actions: IActions; | ||
creators: ICreators; | ||
selectors: ISelectors; | ||
fields: IFieldSelectors; | ||
} | ||
interface IResource extends IResourceDescriptor { | ||
create(props): any; | ||
reducer: (state, action) => any; | ||
saga: () => any; | ||
} | ||
interface IResourceDescriptor { | ||
name: string; | ||
actions: IActions; | ||
creators: ICreators; | ||
selectors: ISelectors; | ||
fields: IFieldSelectors; | ||
hasSameId(left, right): boolean; | ||
} | ||
interface IResource extends IResourceDescriptor { | ||
create(props): any; | ||
reducer: (state, action) => any; | ||
saga: () => any; | ||
} | ||
interface IMiddlewareFactory { | ||
(resource: IResourceDescriptor): IMiddleware; | ||
} | ||
interface IMiddleware { | ||
(action, next: (action?) => any); | ||
} | ||
interface IEditorActions { | ||
EDIT: string; | ||
SELECT: string; | ||
interface IOptions { | ||
id?: string; | ||
} | ||
CREATE: string; | ||
CREATE_CANCEL: string; | ||
CREATE_SUCCESS: string; | ||
CREATE_FAILURE: string; | ||
function createResource(name, options: IOptions, ...middlewares: IMiddlewareFactory[]): IResource; | ||
function httpMiddleware(api, path): IMiddlewareFactory; | ||
function entityHasSameId(l, r): boolean; | ||
READ: string; | ||
READ_CANCEL: string; | ||
READ_SUCCESS: string; | ||
READ_FAILURE: string; | ||
UPDATE: string; | ||
UPDATE_CANCEL: string; | ||
UPDATE_SUCCESS: string; | ||
UPDATE_FAILURE: string; | ||
DELETE: string; | ||
DELETE_CANCEL: string; | ||
DELETE_SUCCESS: string; | ||
DELETE_FAILURE: string; | ||
RESET: string; | ||
} | ||
interface IEditorCreators { | ||
doEdit(item): any; | ||
doSelect(item): any; | ||
doCreate(item): any; | ||
doCreateCancel(item): any; | ||
doCreateSuccess(item): any; | ||
doCreateFailure(item, reason): any; | ||
doRead(item): any; | ||
doReadCancel(item): any; | ||
doReadSuccess(item): any; | ||
doReadFailure(item, reason): any; | ||
doUpdate(item): any; | ||
doUpdateCancel(item): any; | ||
doUpdateSuccess(item): any; | ||
doUpdateFailure(item, reason): any; | ||
doDelete(item): any; | ||
doDeleteCancel(item): any; | ||
doDeleteSuccess(item): any; | ||
doDeleteFailure(item, reason): any; | ||
doReset(): any; | ||
} | ||
interface IEditorSelectors { | ||
opened(state): boolean; | ||
loading(state): boolean; | ||
error(state): string; | ||
item(state): any; | ||
isItem(item): (state) => boolean; | ||
} | ||
interface IEditorDescriptor { | ||
name: string; | ||
actions: IEditorActions; | ||
creators: IEditorCreators; | ||
selectors: IEditorSelectors; | ||
} | ||
interface IEditor extends IEditorDescriptor { | ||
create(props): any; | ||
reducer: (state, action) => any; | ||
saga: () => any; | ||
} | ||
interface IMiddlewareFactory { | ||
(resource: IResourceDescriptor): IMiddleware; | ||
} | ||
interface IMiddleware { | ||
(action, next: (action?) => any); | ||
} | ||
interface IOptions { | ||
id?: string; | ||
} | ||
function createResource(name, options: IOptions, ...middlewares: IMiddlewareFactory[]): IResource; | ||
function createEditor(name, options: IOptions, resource: IResource): IEditor; | ||
function httpMiddleware(api, path): IMiddlewareFactory; | ||
} |
{ | ||
"name": "redux-saga-resources", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "", | ||
"main": "./dist/index.js", | ||
"main": "./dist", | ||
"dependencies": { | ||
@@ -13,6 +13,7 @@ "isomorphic-fetch": "^2.2.1", | ||
"babel-core": "^6.21.0", | ||
"babel-preset-node": "^5.1.1" | ||
"babel-preset-env": "^1.1.8", | ||
"babel-preset-stage-2": "^6.18.0" | ||
}, | ||
"scripts": { | ||
"build": "babel ./src --presets babel-preset-node --out-dir ./dist" | ||
"build": "babel ./src --out-dir ./dist" | ||
}, | ||
@@ -19,0 +20,0 @@ "repository": { |
import { makeTempKey } from '../tempKey'; | ||
import { fields, stripFields } from '../fields'; | ||
import { listAddOrUpdate, listRemoveById } from '../utils/list'; | ||
import { listAddOrUpdate, listRemove } from '../utils/list'; | ||
const ensureId = (item) => { | ||
if (!(fields.id in item)) { | ||
const requireId = (item) => { | ||
if (!item) { | ||
throw new Error(`Expecting item.`); | ||
} | ||
const { [fields.id]: id } = item; | ||
if (!id) { | ||
throw new Error(`Expecting id to be filled, use resource.create({ ... }) to create a new instance.`); | ||
} | ||
return id; | ||
}; | ||
const requireTempId = (item) => { | ||
if (!item) { | ||
throw new Error(`Expecting item.`); | ||
} | ||
const { [fields.tempId]: tempId } = item; | ||
if (!tempId) { | ||
throw new Error(`Expecting tempId to be filled, use resource.create({ ... }) to create a new instance.`); | ||
} | ||
return tempId; | ||
}; | ||
@@ -17,6 +32,6 @@ export default function reducer(descriptor) { | ||
// CREATE | ||
ensureId(action.payload.item); | ||
const internalId = requireTempId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -34,11 +49,9 @@ ...item, | ||
// CREATE - SUCCESS | ||
ensureId(action.payload.item); | ||
const internalId = requireTempId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
...item, | ||
...action.payload.item, | ||
[fields.id]: action.payload.item[fields.newId] || action.payload.item[fields.id], | ||
[fields.newId]: null, | ||
[fields.error]: null, | ||
@@ -54,6 +67,6 @@ [fields.isModified]: false, | ||
// CREATE - SUCCESS | ||
ensureId(action.payload.item); | ||
const internalId = requireTempId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -70,6 +83,6 @@ ...item, | ||
// READ | ||
ensureId(action.payload.item); | ||
const internalId = requireId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -86,6 +99,6 @@ ...item, | ||
// UPDATE | ||
ensureId(action.payload.item); | ||
const internalId = requireId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -103,6 +116,6 @@ ...item, | ||
// UPDATE - CANCEL | ||
ensureId(action.payload.item); | ||
const internalId = requireId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -117,6 +130,6 @@ [fields.error]: null, | ||
// UPDATE - SUCCESS | ||
ensureId(action.payload.item); | ||
const internalId = requireId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -135,6 +148,6 @@ ...item, | ||
// UPDATE - FAILURE | ||
ensureId(action.payload.item); | ||
const internalId = requireId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -150,6 +163,6 @@ ...item, | ||
// DELETE | ||
ensureId(action.payload.item); | ||
const internalId = requireId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -166,6 +179,6 @@ ...item, | ||
// DELETE - CANCEL | ||
ensureId(action.payload.item); | ||
const internalId = requireId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -181,6 +194,6 @@ ...item, | ||
// DELETE - SUCCESS | ||
ensureId(action.payload.item); | ||
const internalId = requireId(action.payload.item); | ||
return { | ||
...state, | ||
list: listRemoveById(state.list, action.payload.item[fields.id]) | ||
list: listRemove(descriptor, state.list, action.payload.item) | ||
}; | ||
@@ -190,6 +203,6 @@ } | ||
// DELETE - FAILURE | ||
ensureId(action.payload.item); | ||
const internalId = requireId(action.payload.item); | ||
return { | ||
...state, | ||
list: listAddOrUpdate(state.list, action.payload.item[fields.id], (item) => { | ||
list: listAddOrUpdate(descriptor, state.list, action.payload.item, (item) => { | ||
return { | ||
@@ -196,0 +209,0 @@ ...item, |
@@ -11,3 +11,3 @@ import { call, fork, takeEvery } from 'redux-saga/effects'; | ||
}, function*(action) { | ||
console.error(`Reached end of middleware.`, action) | ||
console.debug(`Reached end of middleware.`, action) | ||
}); | ||
@@ -14,0 +14,0 @@ } |
@@ -1,5 +0,5 @@ | ||
import { entityHasSameId } from '../'; | ||
import { internal } from '../internal'; | ||
import { fields } from '../fields'; | ||
export default function selectors(name) { | ||
export default function selectors(name, options, hasSameId) { | ||
const scope = (state) => { | ||
@@ -13,6 +13,6 @@ const scope = state[`${name}Resource`]; | ||
error: (state) => scope(state).error, | ||
itemById: (state, id) => scope(state).list.filter(item => entityHasSameId(item, { [fields.id]: id }))[0], | ||
itemByItem: (state, item) => scope(state).list.filter(existing => entityHasSameId(item, existing))[0], | ||
itemById: (id) => (state) => scope(state).list.filter(item => hasSameId(item, { [options.id]: id }))[0], | ||
itemByItem: (item) => (state) => scope(state).list.filter(existing => hasSameId(item, existing))[0], | ||
items: (state) => scope(state).list, | ||
} | ||
} |
@@ -5,3 +5,3 @@ import { internal } from './internal'; | ||
id: internal('id'), | ||
newId: internal('newId'), | ||
tempId: internal('tempId'), | ||
error: internal('error'), | ||
@@ -20,4 +20,5 @@ isModified: internal('isModified'), | ||
export const selectors = { | ||
key: (item) => item[fields.id]||item[fields.tempId], | ||
id: (item) => item[fields.id], | ||
newId: (item) => item[fields.newId], | ||
tempId: (item) => item[fields.tempId], | ||
error: (item) => item[fields.error], | ||
@@ -42,3 +43,4 @@ isModified: (item) => item[fields.isModified], | ||
[fields.id]: id, | ||
[fields.newId]: newId, | ||
[fields.tempId]: tempId, | ||
[fields.error]: error, | ||
[fields.isModified]: isModified, | ||
@@ -55,4 +57,4 @@ [fields.isReading]: isReading, | ||
} = obj; | ||
const cleaned = { id: id, ...remainder }; | ||
const cleaned = { ...remainder }; | ||
return cleaned; | ||
}; |
138
src/index.js
@@ -1,11 +0,34 @@ | ||
import { Effect, CallEffect } from 'redux-saga/effects'; | ||
import { call, fork, put, take, race, takeEvery } from 'redux-saga/effects'; | ||
import { delay } from 'redux-saga'; | ||
import { | ||
Effect, | ||
CallEffect | ||
} from 'redux-saga/effects'; | ||
import { | ||
call, | ||
fork, | ||
put, | ||
take, | ||
race, | ||
takeEvery | ||
} from 'redux-saga/effects'; | ||
import { | ||
delay | ||
} from 'redux-saga'; | ||
import { fields, stripFields, selectors as fieldSelectors } from './fields'; | ||
import { internal, isInternal } from './internal'; | ||
import { makeTempKey, isTempKey } from './tempKey'; | ||
import { | ||
fields, | ||
stripFields, | ||
selectors as fieldSelectors | ||
} from './fields'; | ||
import { | ||
internal, | ||
isInternal | ||
} from './internal'; | ||
import { | ||
makeTempKey, | ||
isTempKey | ||
} from './tempKey'; | ||
import makeActions from './factories/actions'; | ||
import makeCreators from './factories/creators'; | ||
import makeDataSelectors from './factories/dataSelectors'; | ||
import makeReducer from './factories/reducer'; | ||
@@ -15,31 +38,88 @@ import makeSaga from './factories/saga'; | ||
export { httpMiddleware } from './middlewares/http'; | ||
export { | ||
httpMiddleware | ||
} | ||
from './middlewares/http'; | ||
export function createResource(name, options, ...middlewares) { | ||
options = { | ||
id: 'id', | ||
...options | ||
} | ||
options = { | ||
id: 'id', | ||
...options | ||
} | ||
const descriptor = { | ||
name: name, | ||
options: options, | ||
actions: makeActions(name), | ||
creators: makeCreators(name, makeActions(name)), | ||
selectors: makeSelectors(name), | ||
fields: fieldSelectors | ||
}; | ||
const descriptor = { | ||
name: name, | ||
data: makeDataSelectors(options), | ||
options: options, | ||
actions: makeActions(name), | ||
creators: makeCreators(name, makeActions(name)), | ||
selectors: makeSelectors(name, options, entityHasSameId(options)), | ||
fields: fieldSelectors, | ||
hasSameId: entityHasSameId(options) | ||
}; | ||
return { | ||
...descriptor, | ||
create: (props) => ({ ...props, [fields.id]: makeTempKey(), [fields.status]: status.UNSURE }), | ||
reducer: makeReducer(descriptor), | ||
saga: makeSaga(descriptor, ...middlewares.map(f => f(descriptor))) | ||
} | ||
return { | ||
...descriptor, | ||
create: (props) => ({ ...props, | ||
[fields.tempId]: makeTempKey() | ||
}), | ||
reducer: makeReducer(descriptor), | ||
saga: makeSaga(descriptor, ...middlewares.map(f => f(descriptor))) | ||
} | ||
} | ||
export function entityHasSameId(left, right) { | ||
import makeEditorActions from './editor/actions'; | ||
import makeEditorCreators from './editor/creators'; | ||
import makeEditorSelectors from './editor/selectors'; | ||
import makeEditorReducer from './editor/reducer'; | ||
import makeEditorSaga from './editor/saga'; | ||
export function createEditor(name, options, resource, ...middlewares) { | ||
options = { | ||
id: 'id', | ||
...options | ||
} | ||
const descriptor = { | ||
resource: resource, | ||
name: name, | ||
options: options, | ||
actions: makeEditorActions(name), | ||
creators: makeEditorCreators(name, makeEditorActions(name)), | ||
selectors: makeEditorSelectors(name, options, resource), | ||
}; | ||
return { | ||
...descriptor, | ||
reducer: makeEditorReducer(descriptor), | ||
saga: makeEditorSaga(descriptor, ...middlewares.map(f => f(descriptor))) | ||
} | ||
} | ||
function entityHasSameId(options) { | ||
const { id: internalId, tempId } = fields; | ||
const { id } = options; | ||
var leftId, rightId; | ||
return (left, right) => { | ||
if (left === right) return true; | ||
if (!left || !right) return false; | ||
return left[fields.id] === right[fields.id]; | ||
} | ||
if (left && right) { | ||
// Internal ID | ||
leftId = left[internalId]; | ||
rightId = right[internalId]; | ||
if (leftId && (leftId === rightId)) return true; | ||
// Object ID | ||
if (id) { | ||
leftId = left[id]; | ||
rightId = right[id]; | ||
if (leftId && (leftId === rightId)) return true; | ||
} | ||
// Temporary ID | ||
leftId = left[tempId]; | ||
rightId = right[tempId]; | ||
if (leftId && (leftId === rightId)) return true; | ||
} | ||
return false; | ||
}; | ||
} |
@@ -48,5 +48,8 @@ import { | ||
return next => function*(action) { | ||
const key = action.payload.item[fields.id]; | ||
const { id, ...item } = stripFields(action.payload.item); | ||
const tempId = action.payload.item[fields.tempId]; | ||
const { | ||
id, | ||
...item | ||
} = stripFields(action.payload.item); | ||
const { | ||
res, | ||
@@ -63,3 +66,7 @@ cancel | ||
const data = yield call(() => res.json()); | ||
yield put(descriptor.creators.doCreateSuccess({ [fields.id]: key, [fields.newId]: data.id, ...data })); | ||
yield put(descriptor.creators.doCreateSuccess({ | ||
...action.payload.item, | ||
...data, | ||
[fields.id]: descriptor.data.id(data) | ||
})); | ||
yield* next(); | ||
@@ -79,3 +86,3 @@ } else if (cancel) { | ||
return next => function*(action) { | ||
const key = action.payload.item[fields.id]; | ||
const key = descriptor.data.id(action.payload.item); | ||
const item = stripFields(action.payload.item); | ||
@@ -94,3 +101,7 @@ const { | ||
const data = yield call(() => res.json()); | ||
yield put(descriptor.creators.doReadSuccess({ [fields.id]: key, ...data })); | ||
yield put(descriptor.creators.doReadSuccess({ | ||
...action.payload.item, | ||
...data, | ||
[fields.id]: key | ||
})); | ||
yield* next(); | ||
@@ -110,9 +121,14 @@ } else if (cancel) { | ||
return next => function*(action) { | ||
const key = action.payload.item[fields.id]; | ||
const { id, ...item } = stripFields(action.payload.item); | ||
const key = descriptor.data.id(action.payload.item); | ||
const { | ||
id, | ||
...item | ||
} = stripFields(action.payload.item); | ||
const { | ||
res, | ||
cancel | ||
} = yield race({ | ||
res: api.patch(`${path}/${key}`, { ...item, id: key }), | ||
res: api.patch(`${path}/${key}`, { ...item, | ||
id: key | ||
}), | ||
cancel: take([descriptor.actions.UPDATE_CANCEL, descriptor.actions.RESET]), | ||
@@ -125,3 +141,7 @@ timeout: call(delay, configTimeout) | ||
const data = yield call(() => res.json()); | ||
yield put(descriptor.creators.doUpdateSuccess({ [fields.id]: key, [fields.newId]: data.id, ...data })); | ||
yield put(descriptor.creators.doUpdateSuccess({ | ||
...action.payload.item, | ||
...data, | ||
[fields.id]: data.id | ||
})); | ||
yield* next(); | ||
@@ -147,3 +167,3 @@ } else if (cancel) { | ||
const key = action.payload.item[fields.id]; | ||
const key = descriptor.data.id(action.payload.item); | ||
const item = stripFields(action.payload.item); | ||
@@ -176,3 +196,2 @@ const { | ||
return next => function*(action) { | ||
console.log(`LIST ${path}`, action) | ||
const { | ||
@@ -190,3 +209,7 @@ res, | ||
const data = yield call(() => res.json()); | ||
yield put(descriptor.creators.doListSuccess(data.map(item => ({ [fields.id]: item.id, [fields.isRead]: true, ...item })))); | ||
yield put(descriptor.creators.doListSuccess(data.map(item => ({ | ||
[fields.id]: descriptor.data.id(item), | ||
[fields.isRead]: true, | ||
...item | ||
})))); | ||
yield* next(); | ||
@@ -208,2 +231,2 @@ } else if (cancel) { | ||
}; | ||
} | ||
} |
import { fields } from '../fields'; | ||
export function listAddOrUpdate(list, id, transform) { | ||
export function listAddOrUpdate(descriptor, list, bareItem, transform) { | ||
const { hasSameId } = descriptor; | ||
var count = 0; | ||
const res = list.map((item) => { | ||
if (item[fields.id] !== id) { | ||
if (!hasSameId(item, bareItem)) { | ||
return item; | ||
@@ -11,3 +12,4 @@ } | ||
++count; | ||
return transform(item); | ||
const res = transform(item); | ||
return res; | ||
}); | ||
@@ -17,4 +19,3 @@ if (count === 0) { | ||
res.push(transform({ | ||
[fields.id]: id, | ||
[fields.status]: status.UNKNOWN | ||
...bareItem | ||
})); | ||
@@ -25,4 +26,4 @@ } | ||
export function listRemoveById(list, id) { | ||
return list.filter(item => (item[fields.id] !== id)); | ||
export function listRemove(descriptor, list, bareItem) { | ||
return list.filter(item => !descriptor.hasSameId(item, bareItem)); | ||
} |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
183614
40
2606
1
110
4
1