Comparing version 0.0.5 to 0.0.6
@@ -50,24 +50,151 @@ module.exports = | ||
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; }; | ||
var _builder = __webpack_require__(1); | ||
var _datastore = __webpack_require__(1); | ||
module.exports = { | ||
build: _builder.build | ||
}; | ||
var datastore = _interopRequireWildcard(_datastore); | ||
/***/ }, | ||
/* 1 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var _caching = __webpack_require__(3); | ||
'use strict'; | ||
var _caching2 = _interopRequireDefault(_caching); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.build = build; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _decorator = __webpack_require__(2); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
var _datastore = __webpack_require__(5); | ||
module.exports = _extends({}, datastore, { | ||
middleware: { | ||
Caching: _caching2.default | ||
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); } } // Concepts: AbstractEntity | ||
function build(config) { | ||
var abstractEntities = toAbstractFormat(config); | ||
var indexedEntities = toObject(abstractEntities.filter(function (x) { | ||
return !x.val.viewOf; | ||
}), {}); | ||
abstractEntities.forEach(registerViews(indexedEntities)); | ||
abstractEntities.forEach(copyInvalidateToViews(indexedEntities)); | ||
abstractEntities.forEach(setDefaults); | ||
abstractEntities.forEach((0, _decorator.decorateApi)((0, _datastore.createDatastore)(createTtlMap(abstractEntities)))); | ||
return compile(abstractEntities, {}); | ||
} | ||
function createTtlMap(abstractEntities) { | ||
return abstractEntities.reduce(function (memo, value) { | ||
memo[value.name] = value.val.ttl; | ||
return memo; | ||
}, {}); | ||
} | ||
function toAbstractFormat(config) { | ||
return Object.keys(config).map(function (name) { | ||
return { | ||
name: name, | ||
val: config[name] | ||
}; | ||
}); | ||
} | ||
function registerViews(indexedEntities) { | ||
return function (abstractEntity) { | ||
if (isView(abstractEntity)) { | ||
registerView(indexedEntities, abstractEntity); | ||
} | ||
}; | ||
} | ||
function registerView(indexedEntities, abstractEntity) { | ||
assertEntityExist(indexedEntities, abstractEntity); | ||
addView(indexedEntities[getViewOf(abstractEntity)], abstractEntity); | ||
} | ||
function assertEntityExist(indexedEntities, abstractEntity) { | ||
if (!indexedEntities[getViewOf(abstractEntity)]) { | ||
throw new Error('Tried to register view on ' + getViewOf(abstractEntity) + ' which does not exist'); | ||
} | ||
}); | ||
} | ||
function addView(entity, abstractEntity) { | ||
if (!entity.views) { | ||
entity.views = []; | ||
} | ||
entity.views.push(getName(abstractEntity)); | ||
} | ||
function getName(abstractEntity) { | ||
return abstractEntity.name; | ||
} | ||
function getViewOf(abstractEntity) { | ||
return abstractEntity.val.viewOf; | ||
} | ||
function isView(abstractEntity) { | ||
return !!abstractEntity.val.viewOf; | ||
} | ||
function copyInvalidateToViews(indexedEntities) { | ||
return function (abstractEntity) { | ||
if (isView(abstractEntity)) { | ||
assertEntityExist(indexedEntities, abstractEntity); | ||
addInvalidates(abstractEntity, getInvalidates(indexedEntities[getViewOf(abstractEntity)])); | ||
} | ||
}; | ||
} | ||
function setDefaults(abstractEntity) { | ||
if (!abstractEntity.val.invalidates) { | ||
abstractEntity.val.invalidates = []; | ||
} | ||
if (!abstractEntity.val.views) { | ||
abstractEntity.val.views = []; | ||
} | ||
} | ||
function addInvalidates(abstractEntity, invalidates) { | ||
if (abstractEntity.val.invalidates) { | ||
var _abstractEntity$val$i; | ||
(_abstractEntity$val$i = abstractEntity.val.invalidates).push.apply(_abstractEntity$val$i, _toConsumableArray(invalidates)); | ||
} else { | ||
abstractEntity.val.invalidates = invalidates; | ||
} | ||
} | ||
function getInvalidates(entity) { | ||
return entity.invalidates; | ||
} | ||
function toObject(val, obj) { | ||
if (!Array.isArray(val)) { | ||
return val; | ||
} | ||
val.forEach(function (x) { | ||
obj[x.name] = toObject(x.val, {}); | ||
}); | ||
return obj; | ||
} | ||
function compile(val, obj) { | ||
if (!Array.isArray(val)) { | ||
return val; | ||
} | ||
val.forEach(function (x) { | ||
obj[x.name] = toObject(x.val.decoratedApi, {}); | ||
}); | ||
return obj; | ||
} | ||
/***/ }, | ||
/* 1 */ | ||
/* 2 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -80,240 +207,319 @@ | ||
}); | ||
exports.decorateApi = decorateApi; | ||
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; }; | ||
var _create = __webpack_require__(3); | ||
exports.createDatastore = createDatastore; | ||
exports.registerApi = registerApi; | ||
exports.registerMiddleware = registerMiddleware; | ||
exports.build = build; | ||
var _read = __webpack_require__(8); | ||
var _identityMiddleware = __webpack_require__(2); | ||
var _update = __webpack_require__(9); | ||
var IdentityMiddleware = _interopRequireWildcard(_identityMiddleware); | ||
var _delete = __webpack_require__(10); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
// Concepts: AbstractEntity | ||
function decorateApi(datastore) { | ||
return function (abstractEntity) { | ||
var api = getApi(abstractEntity); | ||
var decoratedApi = decorateEveryApiFn(api, abstractEntity, datastore); | ||
addDecoratedApi(abstractEntity, decoratedApi); | ||
}; | ||
} | ||
function _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); } | ||
function getApi(abstractEntity) { | ||
return abstractEntity.val.api; | ||
} | ||
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 decorateEveryApiFn(api, abstractEntity, datastore) { | ||
return Object.keys(api).map(function (name) { | ||
return { | ||
name: name, | ||
val: decorateApiFn(abstractEntity, api[name], datastore) | ||
}; | ||
}); | ||
} | ||
var jobCounter = 0; | ||
function createDatastore() { | ||
return { | ||
_middleware: [{ name: 'identity', middleware: IdentityMiddleware }], | ||
_apis: [], | ||
_built: false | ||
}; | ||
function addDecoratedApi(abstractEntity, decoratedApi) { | ||
abstractEntity.val.decoratedApi = decoratedApi; | ||
} | ||
function registerApi(name, api) { | ||
return function (datastore) { | ||
if (datastore._built) { | ||
throw new Error('Cannot register APIs after built'); | ||
} | ||
function decorateApiFn(abstractEntity, apiFn, datastore) { | ||
var type = abstractEntity.name; | ||
return _extends({}, datastore, { | ||
_apis: [].concat(_toConsumableArray(datastore._apis), [{ name: name, api: api }]) | ||
}); | ||
}; | ||
switch (apiFn.operation) { | ||
case 'CREATE': | ||
return (0, _create.decorateCreate)(apiFn, datastore, abstractEntity); | ||
case 'READ': | ||
return (0, _read.decorateRead)(apiFn, datastore, type); | ||
case 'UPDATE': | ||
return (0, _update.decorateUpdate)(apiFn, datastore, abstractEntity); | ||
case 'DELETE': | ||
return (0, _delete.decorateDelete)(apiFn, datastore, abstractEntity); | ||
} | ||
} | ||
function registerMiddleware(middleware) { | ||
return function (datastore) { | ||
if (datastore._built) { | ||
throw new Error('Cannot register middleware after built'); | ||
} | ||
/***/ }, | ||
/* 3 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
return _extends({}, datastore, { | ||
_middleware: [].concat(_toConsumableArray(datastore._middleware), [{ middleware: middleware }]) | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.decorateCreate = decorateCreate; | ||
var _invalidator = __webpack_require__(4); | ||
var _query = __webpack_require__(6); | ||
var _datastore = __webpack_require__(5); | ||
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 decorateCreate(apiFn, datastore, abstractEntity) { | ||
var type = abstractEntity.name; | ||
return function (item) { | ||
var createPromise = apiFn(item); | ||
var insertId = (0, _datastore.createItem)(datastore, (0, _query.createQueryFromItem)(type, item), item, createPromise); | ||
createInViews(datastore, abstractEntity, item, insertId); | ||
createPromise.then(function (result) { | ||
replaceTempIdInItemAndViews(datastore, abstractEntity, insertId, result); | ||
(0, _invalidator.invalidate)(datastore, abstractEntity, 'CREATE'); | ||
}); | ||
return createPromise; | ||
}; | ||
} | ||
function build(datastore) { | ||
var builtDatastore = { | ||
_built: true | ||
}; | ||
function replaceTempIdInItemAndViews(datastore, abstractEntity, insertId, result) { | ||
var types = [abstractEntity.name].concat(_toConsumableArray(abstractEntity.val.views)); | ||
types.forEach(function (type) { | ||
(0, _datastore.replaceTempId)(datastore, (0, _query.createQuery)(type, insertId), result.id); | ||
}); | ||
} | ||
var apis = datastore._apis.map(buildApi(datastore._middleware)); | ||
apis.forEach(function (api) { | ||
return builtDatastore[api._name] = api; | ||
function createInViews(datastore, abstractEntity, item, insertId) { | ||
var types = abstractEntity.val.views; | ||
types.forEach(function (type) { | ||
(0, _datastore.addItem)(datastore, (0, _query.createQuery)(type, insertId), item); | ||
}); | ||
return builtDatastore; | ||
} | ||
function buildApi(middleware) { | ||
return function (api) { | ||
var readMethods = Object.keys(api.api).filter(function (x) { | ||
return api.api[x].type === 'READ'; | ||
}); | ||
readMethods = createObject(readMethods, readMethods.map(decorateRead(api, middleware))); | ||
/***/ }, | ||
/* 4 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var writeMethods = Object.keys(api.api).filter(function (x) { | ||
return api.api[x].type === 'WRITE'; | ||
}); | ||
writeMethods = createObject(writeMethods, writeMethods.map(decorateWrite(api, middleware))); | ||
'use strict'; | ||
var deleteMethods = Object.keys(api.api).filter(function (x) { | ||
return api.api[x].type === 'DELETE'; | ||
}); | ||
deleteMethods = createObject(deleteMethods, deleteMethods.map(decorateDelete(api, middleware))); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.invalidate = invalidate; | ||
return _extends({ | ||
_name: api.name | ||
}, readMethods, writeMethods, deleteMethods); | ||
}; | ||
var _datastore = __webpack_require__(5); | ||
function invalidate(datastore, abstractEntity, operation) { | ||
var invalidateOn = abstractEntity.val.invalidatesOn || ['CREATE']; | ||
if (invalidateOn.indexOf(operation) === -1) { | ||
return; | ||
} | ||
abstractEntity.val.invalidates.forEach(function (type) { | ||
(0, _datastore.invalidate)(datastore, type); | ||
}); | ||
} | ||
function decorateRead(api, middleware) { | ||
return function (toDecorate) { | ||
return function () { | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
/***/ }, | ||
/* 5 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var preRead = bindPreRead('preRead', api.name, api.api[toDecorate], toDecorate, middleware.filter(function (x) { | ||
return x.middleware.preRead; | ||
})); | ||
var result = preRead(args); | ||
'use strict'; | ||
var postReadMiddleware = middleware.filter(function (x) { | ||
return x.middleware.postRead; | ||
}); | ||
var methodMeta = createMethodMeta(api.api[toDecorate]); | ||
postReadMiddleware.forEach(function (x) { | ||
return x.middleware.postRead(api.name, toDecorate, methodMeta, args, result); | ||
}); | ||
return result.then(function (x) { | ||
return x.data; | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; | ||
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; }; // Concepts: | ||
// Datastore - reference for datastore | ||
// Item - a single entity, which contains all info to perform operations | ||
exports.createDatastore = createDatastore; | ||
exports.createItem = createItem; | ||
exports.replaceTempId = replaceTempId; | ||
exports.addItem = addItem; | ||
exports.getItem = getItem; | ||
exports.updateItem = updateItem; | ||
exports.deleteItem = deleteItem; | ||
exports.addCollection = addCollection; | ||
exports.getCollection = getCollection; | ||
exports.invalidate = invalidate; | ||
exports.patchItem = patchItem; | ||
var _query = __webpack_require__(6); | ||
var _merger = __webpack_require__(7); | ||
function createDatastore(ttlMap) { | ||
return { | ||
queryCache: {}, | ||
entityCache: {}, | ||
incrementingId: 1, | ||
ttlMap: ttlMap, | ||
tempToRealId: {} | ||
}; | ||
} | ||
function bindPreRead(hook, apiName, toDecorate, toDecorateName, middleware) { | ||
var _middleware = _toArray(middleware); | ||
function createItem(datastore, query, value, promise) { | ||
var id = 'tmp-' + datastore.incrementingId++; | ||
query.value = id; | ||
addItem(datastore, query, value); | ||
addTemporaryToRealId(datastore, id, promise); | ||
return id; | ||
} | ||
var x = _middleware[0]; | ||
function replaceTempId(datastore, query, realId) { | ||
var item = getItemSync(datastore, query); | ||
deleteItemSync(datastore, query); | ||
addItem(datastore, _extends({}, query, { value: realId }), item); | ||
} | ||
var xs = _middleware.slice(1); | ||
function addTemporaryToRealId(datastore, tmpId, realId) { | ||
datastore.tempToRealId[tmpId] = realId; | ||
} | ||
var methodMeta = createMethodMeta(toDecorate); | ||
if (xs.length === 0) { | ||
return x.middleware[hook].bind(null, function (args) { | ||
return toDecorate.apply(undefined, _toConsumableArray(args)); | ||
}, apiName, toDecorateName, methodMeta); | ||
function replaceTempIdInQuery(datastore, query) { | ||
if (isQueryForTempId(query) && !entityExist(datastore, query)) { | ||
// Try to get item with id, if not exist try with id from translation table | ||
return datastore.tempToRealId[query.value].then(function (newId) { | ||
return (0, _query.createQuery)(query.type, newId); | ||
}); | ||
} else { | ||
return x.middleware[hook].bind(null, bindPreRead(hook, apiName, toDecorate, toDecorateName, xs), apiName, toDecorateName, methodMeta); | ||
return Promise.resolve(query); | ||
} | ||
} | ||
function bindPreWrite(hook, apiName, toDecorate, toDecorateName, jobId, middleware) { | ||
var _middleware2 = _toArray(middleware); | ||
function isQueryForTempId(query) { | ||
return (/^tmp-/.test(query.value) | ||
); | ||
} | ||
var x = _middleware2[0]; | ||
function entityExist(datastore, query) { | ||
return !!datastore.entityCache[createKey(query)]; | ||
} | ||
var xs = _middleware2.slice(1); | ||
function addItem(datastore, query, value) { | ||
datastore.entityCache[createKey(query)] = withTimestamp(value, Date.now()); | ||
} | ||
var methodMeta = createMethodMeta(toDecorate); | ||
if (xs.length === 0) { | ||
return x.middleware[hook].bind(null, function (args) { | ||
return toDecorate.apply(undefined, _toConsumableArray(args)); | ||
}, apiName, toDecorateName, methodMeta, jobId); | ||
} else { | ||
return x.middleware[hook].bind(null, bindPreWrite(hook, apiName, toDecorate, toDecorateName, jobId, xs), apiName, toDecorateName, methodMeta, jobId); | ||
function getItem(datastore, query) { | ||
return replaceTempIdInQuery(datastore, query).then(function (translatedQuery) { | ||
return getItemSync(datastore, translatedQuery); | ||
}); | ||
} | ||
function getItemSync(datastore, query) { | ||
var item = datastore.entityCache[createKey(query)]; | ||
var ttl = datastore.ttlMap[query.type]; | ||
if (item && (isQueryForTempId(query) || hasExpired(item.timestamp, ttl))) { | ||
return withoutTimestamp(item); | ||
} | ||
} | ||
function decorateWrite(api, middleware) { | ||
return function (toDecorate) { | ||
return function () { | ||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
function hasExpired(timestamp, ttl) { | ||
return (Date.now() - timestamp) / 1000 < ttl; | ||
} | ||
var jobId = jobCounter++; | ||
function updateItem(datastore, query, value) { | ||
return replaceTempIdInQuery(datastore, query).then(function (translatedQuery) { | ||
return datastore.entityCache[createKey(translatedQuery)] = withTimestamp(value, Date.now()); | ||
}); | ||
} | ||
var preWrite = bindPreWrite('preWrite', api.name, api.api[toDecorate], toDecorate, jobId, middleware.filter(function (x) { | ||
return x.middleware.preWrite; | ||
})); | ||
var result = preWrite(args); | ||
function deleteItem(datastore, query) { | ||
return replaceTempIdInQuery(datastore, query).then(function (translatedQuery) { | ||
deleteItemSync(datastore, translatedQuery); | ||
}); | ||
} | ||
var postWriteMiddleware = middleware.filter(function (x) { | ||
return x.middleware.postWrite; | ||
}); | ||
var methodMeta = createMethodMeta(api.api[toDecorate]); | ||
postWriteMiddleware.forEach(function (x) { | ||
return x.middleware.postWrite(api.name, toDecorate, methodMeta, jobId, args, result); | ||
}); | ||
return result.then(function (x) { | ||
return x.data; | ||
}); | ||
}; | ||
}; | ||
function deleteItemSync(datastore, query) { | ||
delete datastore.entityCache[createKey(query)]; | ||
} | ||
function bindPreDelete(hook, apiName, toDecorate, toDecorateName, jobId, middleware) { | ||
var _middleware3 = _toArray(middleware); | ||
function addCollection(datastore, query, value) { | ||
var ids = value.map(function (x) { | ||
return x.id; | ||
}); | ||
value.forEach(function (x) { | ||
var queryForItem = (0, _query.createQuery)(query.type, x.id); | ||
addItem(datastore, queryForItem, x); | ||
}); | ||
var x = _middleware3[0]; | ||
if (!datastore.queryCache[query.type]) { | ||
datastore.queryCache[query.type] = {}; | ||
} | ||
var xs = _middleware3.slice(1); | ||
return datastore.queryCache[query.type][createKey(query)] = withTimestamp(ids, Date.now()); | ||
} | ||
var methodMeta = createMethodMeta(toDecorate); | ||
if (xs.length === 0) { | ||
return x.middleware[hook].bind(null, function (args) { | ||
return toDecorate.apply(undefined, _toConsumableArray(args)); | ||
}, apiName, toDecorateName, methodMeta, jobId); | ||
function getCollection(datastore, query) { | ||
var collection = safeCollectionLookup(datastore, query); | ||
var ttl = datastore.ttlMap[query.type]; | ||
if (collection && hasExpired(collection.timestamp, ttl)) { | ||
return Promise.all(withoutTimestamp(collection).map(function (id) { | ||
return getItemSync(datastore, (0, _query.createQuery)(query.type, id)); | ||
}).filter(function (x) { | ||
return x !== undefined; | ||
})); | ||
} else { | ||
return x.middleware[hook].bind(null, bindPreWrite(hook, apiName, toDecorate, toDecorateName, jobId, xs), apiName, toDecorateName, methodMeta, jobId); | ||
return Promise.resolve(undefined); | ||
} | ||
} | ||
function decorateDelete(api, middleware) { | ||
return function (toDecorate) { | ||
return function () { | ||
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { | ||
args[_key3] = arguments[_key3]; | ||
} | ||
function invalidate(datastore, type) { | ||
if (datastore.queryCache) { | ||
datastore.queryCache[type] = {}; | ||
} | ||
} | ||
var jobId = jobCounter++; | ||
function patchItem(datastore, query, item) { | ||
getItem(datastore, query).then(function (superItem) { | ||
if (superItem) { | ||
updateItem(datastore, query, (0, _merger.merge)(item, superItem)); | ||
} | ||
}); | ||
} | ||
var preDelete = bindPreDelete('preDelete', api.name, api.api[toDecorate], toDecorate, jobId, middleware.filter(function (x) { | ||
return x.middleware.preDelete; | ||
})); | ||
var result = preDelete(args); | ||
function safeCollectionLookup(datastore, query) { | ||
return (datastore.queryCache[query.type] || {})[createKey(query)]; | ||
} | ||
var postDeleteMiddleware = middleware.filter(function (x) { | ||
return x.middleware.postDelete; | ||
}); | ||
var methodMeta = createMethodMeta(api.api[toDecorate]); | ||
postDeleteMiddleware.forEach(function (x) { | ||
return x.middleware.postDelete(api.name, toDecorate, methodMeta, jobId, args, result); | ||
}); | ||
return result.then(function (x) { | ||
return x.data; | ||
}); | ||
}; | ||
}; | ||
function createKey(query) { | ||
return Object.keys(query).map(function (x) { | ||
if (_typeof(query[x]) === 'object') { | ||
return createKey(query[x]); | ||
} else { | ||
return query[x]; | ||
} | ||
}).join('-'); | ||
} | ||
function createMethodMeta(method) { | ||
function withTimestamp(value, timestamp) { | ||
return { | ||
multipleEntities: method.multipleEntities, | ||
entity: method.entity | ||
timestamp: timestamp, | ||
value: value | ||
}; | ||
} | ||
function createObject(keys, vals) { | ||
var obj = {}; | ||
keys.forEach(function (key, index) { | ||
return obj[key] = vals[index]; | ||
}); | ||
return obj; | ||
function withoutTimestamp(valueWithTimestamp) { | ||
return valueWithTimestamp.value; | ||
} | ||
/***/ }, | ||
/* 2 */ | ||
/* 6 */ | ||
/***/ function(module, exports) { | ||
@@ -326,32 +532,28 @@ | ||
}); | ||
exports.preRead = preRead; | ||
exports.preWrite = preWrite; | ||
exports.postRead = postRead; | ||
exports.postWrite = postWrite; | ||
exports.preDelete = preDelete; | ||
exports.postDelete = postDelete; | ||
function preRead(next, apiName, toDecorateName, multipleEntities, args) { | ||
return next(args); | ||
} | ||
function preWrite(next, apiName, methodName, methodMeta, jobId, args) { | ||
return next(args); | ||
} | ||
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 postRead() {} | ||
function postWrite(promise) { | ||
return promise; | ||
exports.createQuery = createQuery; | ||
exports.createQueryFromItem = createQueryFromItem; | ||
function createQuery(type, value, moreIdentifiers) { | ||
if (moreIdentifiers) { | ||
return _extends({ | ||
type: type | ||
}, moreIdentifiers, { | ||
value: value | ||
}); | ||
} else { | ||
return { | ||
type: type, | ||
value: value | ||
}; | ||
} | ||
} | ||
function preDelete(next, apiName, methodName, methodMeta, jobId, args) { | ||
return next(args); | ||
function createQueryFromItem(type, item) { | ||
return createQuery(type, item.id); | ||
} | ||
function postDelete(promise) { | ||
return promise; | ||
} | ||
/***/ }, | ||
/* 3 */ | ||
/* 7 */ | ||
/***/ function(module, exports) { | ||
@@ -364,243 +566,192 @@ | ||
}); | ||
exports.default = Caching; | ||
function Caching(config) { | ||
var storage = { | ||
dummyItem: { | ||
timestamp: 1212 | ||
} | ||
}; | ||
var collectionQueries = { | ||
dummyItem: { | ||
timestamp: 1212 | ||
} | ||
}; | ||
var temporaryIds = {}; | ||
return { | ||
preRead: preRead, | ||
postRead: postRead, | ||
preWrite: preWrite, | ||
postWrite: postWrite, | ||
postDelete: postDelete, | ||
preDelete: preDelete | ||
}; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; | ||
function preRead(next, apiName, methodName, methodMeta, args) { | ||
var typeConfig = getTypeConfig(apiName, methodMeta.entity); | ||
var key = createKey(apiName, methodName, methodMeta.multipleEntities, args, methodMeta.entity); | ||
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; }; | ||
var fromCache = void 0; | ||
if (typeConfig && (fromCache = getFromCache(typeConfig, key))) { | ||
return new Promise(function (resolve) { | ||
return resolve(fromCache); | ||
}); | ||
} else { | ||
return next(args); | ||
exports.merge = merge; | ||
function merge(source, destination) { | ||
var result = _extends({}, destination); | ||
var keysForNonObjects = getNonObjectKeys(source); | ||
keysForNonObjects.forEach(function (key) { | ||
if (destination[key] !== undefined) { | ||
result[key] = source[key]; | ||
} | ||
} | ||
}); | ||
function postRead(apiName, methodName, methodMeta, args, promise) { | ||
var type = methodMeta.entity; | ||
var keysForObjects = getObjectKeys(source); | ||
keysForObjects.forEach(function (key) { | ||
if (destination[key] !== undefined) { | ||
result[key] = merge(source[key], destination[key]); | ||
} | ||
}); | ||
promise.then(function (result) { | ||
saveToCache(createKey(apiName, methodName, methodMeta.multipleEntities, args, type), { data: result.data }); | ||
}); | ||
} | ||
return result; | ||
} | ||
function preWrite(next, apiName, methodName, methodMeta, jobId, args) { | ||
var methodType = methodMeta.entity; | ||
var key = createKey(apiName, methodName, methodMeta.multipleEntities, args, methodType, jobId); | ||
saveToCache(key, { | ||
data: args[0] | ||
}, 'WRITE'); | ||
return next(args); | ||
} | ||
function getNonObjectKeys(object) { | ||
return Object.keys(object).filter(function (key) { | ||
return object[key] === null || _typeof(object[key]) !== 'object' || Array.isArray(object[key]); | ||
}); | ||
} | ||
function postWrite(apiName, methodName, methodMeta, jobId, args, promise) { | ||
if (temporaryIds[jobId] !== undefined) { | ||
temporaryIds[jobId].promise = promise; | ||
} | ||
function getObjectKeys(object) { | ||
return Object.keys(object).filter(function (key) { | ||
return object[key] !== null && !Array.isArray(object[key]) && _typeof(object[key]) === 'object'; | ||
}); | ||
} | ||
var config = getTypeConfig(apiName, methodMeta.entity); | ||
/***/ }, | ||
/* 8 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
promise.then(replaceTemporaryWithFinalId(methodMeta, jobId)).then(invalidateCacheIfDesired(config, methodMeta.entity, args)); | ||
'use strict'; | ||
return promise; | ||
} | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.decorateRead = decorateRead; | ||
function preDelete(next, apiName, methodName, methodMeta, jobId, args) { | ||
if (methodMeta.multipleEntities) { | ||
args[0].map(deleteFromCache(methodMeta.entity)); | ||
} else { | ||
deleteFromCache(methodMeta.entity)(args[0]); | ||
} | ||
var _query = __webpack_require__(6); | ||
return next(args); | ||
} | ||
var _datastore = __webpack_require__(5); | ||
function deleteFromCache(type) { | ||
return function (entity) { | ||
delete storage[type][entity.id]; | ||
}; | ||
} | ||
function decorateRead(apiFn, datastore, type) { | ||
return function (query) { | ||
var fromCache = getFromCache(apiFn, datastore, type, query); | ||
return fromCache.then(function (itemFromCache) { | ||
if (itemFromCache) { | ||
return itemFromCache; | ||
} else { | ||
var result = apiFn(query); | ||
result.then(addToCache(apiFn, datastore, type, query)); | ||
return result; | ||
} | ||
}); | ||
}; | ||
} | ||
function postDelete(promise) { | ||
return promise; | ||
function getFromCache(apiFn, datastore, type, query) { | ||
if (shouldUseQueryCache(apiFn.plural, apiFn.byId)) { | ||
return getFromQueryCache(datastore, type, query, apiFn.name); | ||
} else { | ||
return getFromEntityCache(datastore, type, query); | ||
} | ||
} | ||
function invalidateCacheIfDesired(config, entityType, args) { | ||
if (newEntityWasCreated(args[0]) && config.invalidateOnCreate) { | ||
collectionQueries[entityType] = {}; | ||
} | ||
} | ||
function shouldUseQueryCache(plural, byId) { | ||
return plural === true || byId === false; | ||
} | ||
function newEntityWasCreated(entity) { | ||
return entity.id === undefined; | ||
} | ||
function getFromQueryCache(datastore, type, query, apiFnName) { | ||
return (0, _datastore.getCollection)(datastore, createQueryForCollection(type, query, apiFnName)); | ||
} | ||
function replaceTemporaryWithFinalId(methodMeta, jobId) { | ||
return function (realEntity) { | ||
var tempId = temporaryIds[jobId].id; | ||
var entityWithTempId = storage[methodMeta.entity][tempId]; | ||
delete storage[methodMeta.entity][tempId]; | ||
storage[methodMeta.entity][realEntity.data.id] = entityWithTempId; | ||
}; | ||
} | ||
function getFromEntityCache(datastore, type, id) { | ||
return (0, _datastore.getItem)(datastore, (0, _query.createQuery)(type, id)); | ||
} | ||
function createKey(apiName, methodName, multipleEntities, args, type, jobId) { | ||
if (multipleEntities) { | ||
return { | ||
type: 'COLLECTION_KEY', | ||
value: [apiName, methodName, multipleEntities, args].join('-'), | ||
entityType: type | ||
}; | ||
function addToCache(apiFn, datastore, type, query) { | ||
return function (data) { | ||
if (shouldUseQueryCache(apiFn.plural, apiFn.byId)) { | ||
(0, _datastore.addCollection)(datastore, createQueryForCollection(type, query, apiFn.name), data); | ||
} else { | ||
return { | ||
type: 'ENTITY_KEY', | ||
entityType: type, | ||
id: args[0].id || createTemporaryId(jobId) | ||
}; | ||
(0, _datastore.addItem)(datastore, (0, _query.createQuery)(type, query), data); | ||
} | ||
} | ||
}; | ||
} | ||
function createTemporaryId(jobId) { | ||
var id = generateEntityIdFromJobId(jobId); | ||
temporaryIds[jobId] = { | ||
id: id | ||
}; | ||
return id; | ||
} | ||
function createQueryForCollection(type, query, apiFnName) { | ||
return (0, _query.createQuery)(type, query, { name: apiFnName }); | ||
} | ||
function generateEntityIdFromJobId(jobId) { | ||
return 'TEMPORARY_ID_' + jobId; | ||
} | ||
/***/ }, | ||
/* 9 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
function getTypeConfig(apiName, typeName) { | ||
if (config[typeName]) { | ||
return config[typeName]; | ||
} else { | ||
return {}; | ||
} | ||
} | ||
'use strict'; | ||
function getFromCache(methodConfig, key) { | ||
var value = void 0; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.decorateUpdate = decorateUpdate; | ||
if (key.type === 'COLLECTION_KEY') { | ||
value = getCollectionFromCache(key); | ||
} else { | ||
value = getEntityFromCache(key); | ||
} | ||
var _invalidator = __webpack_require__(4); | ||
if (value && isValid(value, methodConfig, key)) { | ||
return value; | ||
} else { | ||
return false; | ||
} | ||
} | ||
var _query = __webpack_require__(6); | ||
function getCollectionFromCache(key) { | ||
if (collectionQueries[key.entityType] && collectionQueries[key.entityType][key.value]) { | ||
return { | ||
data: collectionQueries[key.entityType][key.value].ids.map(function (x) { | ||
return getEntityDataIfExist(storage[key.entityType][x]); | ||
}).filter(function (x) { | ||
return x !== null; | ||
}) | ||
}; | ||
} else { | ||
return false; | ||
} | ||
} | ||
var _datastore = __webpack_require__(5); | ||
function getEntityDataIfExist(entity) { | ||
if (entity) { | ||
return entity.data; | ||
} else { | ||
return null; | ||
} | ||
} | ||
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 getEntityFromCache(key) { | ||
if (storage[key.entityType][key.id]) { | ||
return storage[key.entityType][key.id]; | ||
} else { | ||
return false; | ||
} | ||
} | ||
function decorateUpdate(apiFn, datastore, abstractEntity) { | ||
return function (item) { | ||
updateItemAndViews(datastore, abstractEntity, item); | ||
updateSuperEntity(datastore, abstractEntity, item); | ||
var result = apiFn(item); | ||
result.then(function () { | ||
(0, _invalidator.invalidate)(datastore, abstractEntity, 'UPDATE'); | ||
}); | ||
return result; | ||
}; | ||
} | ||
function isValid(item, methodConfig, key) { | ||
if (key.type === 'COLLECTION_KEY') { | ||
return collectionQueries[key.entityType][key.value].timestamp + methodConfig.ttl * 1000 >= Date.now(); | ||
} else { | ||
return item.timestamp + methodConfig.ttl * 1000 >= Date.now(); | ||
} | ||
function updateItemAndViews(datastore, abstractEntity, item) { | ||
var types = [abstractEntity.name].concat(_toConsumableArray(abstractEntity.val.views)); | ||
types.forEach(function (type) { | ||
(0, _datastore.updateItem)(datastore, (0, _query.createQueryFromItem)(type, item), item); | ||
}); | ||
} | ||
function updateSuperEntity(datastore, abstractEntity, item) { | ||
var superEntity = abstractEntity.val.viewOf; | ||
if (!superEntity) { | ||
return; | ||
} | ||
(0, _datastore.patchItem)(datastore, (0, _query.createQueryFromItem)(superEntity, item), item); | ||
} | ||
function saveToCache(key, val, operation) { | ||
var type = key.entityType; | ||
if (!storage[type]) { | ||
storage[type] = {}; | ||
} | ||
/***/ }, | ||
/* 10 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
if (key.type === 'COLLECTION_KEY') { | ||
saveCollection(key, type, val.data, operation); | ||
} else { | ||
saveEntity(key, type, val.data); | ||
} | ||
} | ||
'use strict'; | ||
function saveCollection(key, type, val, operation) { | ||
val.forEach(function (x) { | ||
storage[type][x.id] = { | ||
data: x, | ||
timestamp: Date.now() | ||
}; | ||
}); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.decorateDelete = decorateDelete; | ||
if (operation !== 'WRITE') { | ||
var ids = val.map(function (x) { | ||
return x.id; | ||
}); | ||
var _invalidator = __webpack_require__(4); | ||
if (!collectionQueries[key.entityType]) { | ||
collectionQueries[key.entityType] = {}; | ||
} | ||
var _query = __webpack_require__(6); | ||
collectionQueries[key.entityType][key.value] = { | ||
timestamp: Date.now(), | ||
ids: ids | ||
}; | ||
} | ||
} | ||
var _datastore = __webpack_require__(5); | ||
function saveEntity(key, type, val) { | ||
storage[type][key.id] = { | ||
data: val, | ||
timestamp: Date.now() | ||
}; | ||
} | ||
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 decorateDelete(apiFn, datastore, abstractEntity) { | ||
return function (id) { | ||
deleteFromEntityAndViews(datastore, abstractEntity, id); | ||
var result = apiFn(id); | ||
result.then(function () { | ||
(0, _invalidator.invalidate)(datastore, abstractEntity, 'DELETE'); | ||
}); | ||
return result; | ||
}; | ||
} | ||
function deleteFromEntityAndViews(datastore, abstractEntity, id) { | ||
var types = [abstractEntity.val.viewOf, abstractEntity.name].concat(_toConsumableArray(abstractEntity.val.views)).filter(function (x) { | ||
return x; | ||
}); | ||
types.forEach(function (type) { | ||
(0, _datastore.deleteItem)(datastore, (0, _query.createQuery)(type, id)); | ||
}); | ||
} | ||
/***/ } | ||
/******/ ]); |
{ | ||
"name": "laddare", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "Data fetching layaer with support for caching", | ||
"main": "dist/bundle.js", | ||
"dependencies": { | ||
"axios": "^0.11.1" | ||
}, | ||
@@ -13,6 +12,10 @@ "devDependencies": { | ||
"babel-preset-es2015": "^6.9.0", | ||
"babel-preset-stage-2": "^6.5.0" | ||
"babel-preset-stage-1": "^6.5.0", | ||
"babel-preset-stage-2": "^6.5.0", | ||
"babel-register": "^6.9.0", | ||
"chai": "^3.5.0", | ||
"mocha": "^2.5.3" | ||
}, | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "./node_modules/.bin/mocha --compilers js:babel-register --reporter spec src/**/*spec.js --require mocha.config" | ||
}, | ||
@@ -19,0 +22,0 @@ "author": "Peter Crona <petercrona89@gmail.com> (http://www.icecoldcode.com)", |
@@ -1,43 +0,38 @@ | ||
import { get, post, delete as remove } from 'axios'; | ||
import { get, post, put, delete as remove } from 'axios'; | ||
getAllPosts.type = 'READ'; | ||
getAllPosts.entity = 'JsonPlacerholderPost'; | ||
getAllPosts.multipleEntities = true; | ||
getAllPosts.operation = 'READ'; | ||
getAllPosts.plural = true; | ||
export function getAllPosts() { | ||
return get('http://jsonplaceholder.typicode.com/posts'); | ||
return get('http://jsonplaceholder.typicode.com/posts').then(x => x.data); | ||
} | ||
getAllPostsWithIdHigerThan.type = 'READ'; | ||
getAllPostsWithIdHigerThan.entity = 'JsonPlacerholderPost'; | ||
getAllPostsWithIdHigerThan.multipleEntities = true; | ||
getAllPostsWithIdHigerThan.operation = 'READ'; | ||
getAllPostsWithIdHigerThan.plural = true; | ||
export function getAllPostsWithIdHigerThan(id) { | ||
return get('http://jsonplaceholder.typicode.com/posts').then(x => { | ||
return { ...x, data: x.data.filter(y => y.id > id) }; | ||
return x.data.filter(y => y.id > id); | ||
}); | ||
} | ||
getSingle.type = 'READ'; | ||
getSingle.entity = 'JsonPlacerholderPost'; | ||
getSingle.multipleEntities = false; | ||
export function getSingle(args) { | ||
return get('http://jsonplaceholder.typicode.com/posts/' + args.id); | ||
getSingle.operation = 'READ'; | ||
getSingle.plural = false; | ||
getSingle.byId = true; | ||
export function getSingle(id) { | ||
return get('http://jsonplaceholder.typicode.com/posts/' + id).then((x) => x.data); | ||
} | ||
savePost.type = 'WRITE'; | ||
savePost.entity = 'JsonPlacerholderPost'; | ||
savePost.multipleEntities = false; | ||
savePost.operation = 'UPDATE'; | ||
savePost.plural = false; | ||
export function savePost(entity) { | ||
return post('http://jsonplaceholder.typicode.com/posts/' + entity.id, { ...entity }); | ||
return put('http://jsonplaceholder.typicode.com/posts/' + entity.id, { ...entity }); | ||
} | ||
createPost.type = 'WRITE'; | ||
createPost.entity = 'JsonPlacerholderPost'; | ||
createPost.multipleEntities = false; | ||
createPost.operation = 'CREATE'; | ||
createPost.plural = false; | ||
export function createPost(entity) { | ||
return post('http://jsonplaceholder.typicode.com/posts', { ...entity }); | ||
return post('http://jsonplaceholder.typicode.com/posts', { ...entity }).then((x)=>x.data); | ||
} | ||
savePosts.type = 'WRITE'; | ||
savePosts.entity = 'JsonPlacerholderPost'; | ||
savePosts.multipleEntities = true; | ||
savePosts.operation = 'UPDATE'; | ||
savePosts.plural = true; | ||
export function savePosts(entity) { | ||
@@ -47,7 +42,6 @@ return post('http://jsonplaceholder.typicode.com/posts/', { ...entity }); | ||
deletePost.type = 'DELETE'; | ||
deletePost.entity = 'JsonPlacerholderPost'; | ||
deletePost.multipleEntities = true; | ||
export function deletePost(entity) { | ||
return remove('http://jsonplaceholder.typicode.com/posts', { ...entity }); | ||
deletePost.operation = 'DELETE'; | ||
deletePost.plural = true; | ||
export function deletePost(id) { | ||
return remove('http://jsonplaceholder.typicode.com/posts/' + id); | ||
} |
const path = require('path'); | ||
module.exports = { | ||
entry: './src/index.js', | ||
entry: './src/release.js', | ||
output: { | ||
@@ -6,0 +6,0 @@ path: __dirname + '/dist', |
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
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
47978
0
26
1219
2
8
1
- Removedaxios@^0.11.1
- Removedaxios@0.11.1(transitive)
- Removeddebug@2.6.9(transitive)
- Removedfollow-redirects@0.0.7(transitive)
- Removedms@2.0.0(transitive)
- Removedstream-consume@0.1.1(transitive)