diff --git a/src/plugins/cache/.tern-port b/src/plugins/cache/.tern-port deleted file mode 100644 index 471d456..0000000 --- a/src/plugins/cache/.tern-port +++ /dev/null @@ -1 +0,0 @@ -46631 \ No newline at end of file diff --git a/src/plugins/cache/cache.js b/src/plugins/cache/cache.js new file mode 100644 index 0000000..220cd91 --- /dev/null +++ b/src/plugins/cache/cache.js @@ -0,0 +1,47 @@ +import {curry} from 'ladda-fp'; +import * as QueryCache from './query-cache'; +import * as EntityStore from './entity-store'; + +export const createCache = (entityConfigs, onChange) => { + const entityStore = EntityStore.createEntityStore(entityConfigs, onChange); + const queryCache = QueryCache.createQueryCache(entityStore, onChange); + return {entityStore, queryCache}; +}; + +export const storeQueryResponse = ({queryCache}, ...args) => { + return QueryCache.put(queryCache, ...args); +}; + +export const getQueryResponse = QueryCache.getValue; + +export const getQueryResponseWithMeta = ({queryCache}, ...args) => { + return QueryCache.get(queryCache, ...args); +}; + +export const containsQueryResponse = ({queryCache}, ...args) => { + return QueryCache.contains(queryCache, ...args); +}; + +export const invalidateQuery = ({queryCache}, ...args) => { + return QueryCache.invalidate(queryCache, ...args); +}; + +export const storeEntity = curry(({entityStore}, ...args) => { + return EntityStore.put(entityStore, ...args); +}); + +export const storeEntities = ({entityStore}, ...args) => { + return EntityStore.mPut(entityStore, ...args); +}; + +export const getEntity = curry(({entityStore}, ...args) => { + return EntityStore.get(entityStore, ...args); +}); + +export const removeEntity = ({entityStore}, ...args) => { + return EntityStore.remove(entityStore, ...args); +}; + +export const containsEntity = ({entityStore}, ...args) => { + return EntityStore.contains(entityStore, ...args); +}; diff --git a/src/plugins/cache/index.js b/src/plugins/cache/index.js index 43808c1..ff26949 100644 --- a/src/plugins/cache/index.js +++ b/src/plugins/cache/index.js @@ -1,6 +1,5 @@ -import {compose, values} from 'ladda-fp'; -import {createEntityStore} from './entity-store'; -import {createQueryCache} from './query-cache'; +import {values} from 'ladda-fp'; +import {createCache} from './cache'; import {decorateCreate} from './operations/create'; import {decorateRead} from './operations/read'; import {decorateUpdate} from './operations/update'; @@ -16,10 +15,9 @@ const HANDLERS = { }; export const cachePlugin = (onChange) => ({ config, entityConfigs }) => { - const entityStore = compose((c) => createEntityStore(c, onChange), values)(entityConfigs); - const queryCache = createQueryCache(entityStore, onChange); + const cache = createCache(values(entityConfigs), onChange); return ({ entity, fn }) => { const handler = HANDLERS[fn.operation]; - return handler(config, entityStore, queryCache, entity, fn); + return handler(config, cache, entity, fn); }; }; diff --git a/src/plugins/cache/operations/.tern-port b/src/plugins/cache/operations/.tern-port deleted file mode 100644 index 2ec04c8..0000000 --- a/src/plugins/cache/operations/.tern-port +++ /dev/null @@ -1 +0,0 @@ -39651 \ No newline at end of file diff --git a/src/plugins/cache/operations/create.js b/src/plugins/cache/operations/create.js index 87382df..93ebf49 100644 --- a/src/plugins/cache/operations/create.js +++ b/src/plugins/cache/operations/create.js @@ -1,12 +1,11 @@ import {passThrough, compose} from 'ladda-fp'; -import {put} from '../entity-store'; -import {invalidate} from '../query-cache'; +import {storeEntity, invalidateQuery} from '../cache'; import {addId} from '../id-helper'; -export function decorateCreate(c, es, qc, e, aFn) { +export function decorateCreate(c, cache, e, aFn) { return (...args) => { return aFn(...args) - .then(passThrough(() => invalidate(qc, e, aFn))) - .then(passThrough(compose(put(es, e), addId(c, aFn, args)))); + .then(passThrough(() => invalidateQuery(cache, e, aFn))) + .then(passThrough(compose(storeEntity(cache, e), addId(c, aFn, args)))); }; } diff --git a/src/plugins/cache/operations/create.spec.js b/src/plugins/cache/operations/create.spec.js index 6de1f0e..7d8bb6c 100644 --- a/src/plugins/cache/operations/create.spec.js +++ b/src/plugins/cache/operations/create.spec.js @@ -1,7 +1,6 @@ import sinon from 'sinon'; import {decorateCreate} from './create'; -import {createEntityStore, get} from '../entity-store'; -import {createQueryCache} from '../query-cache'; +import {createCache, getEntity} from '../cache'; import {createApiFunction} from '../test-helper'; const config = [ @@ -41,17 +40,16 @@ const config = [ describe('Create', () => { describe('decorateCreate', () => { it('Adds value to entity store', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const xOrg = {name: 'Kalle'}; const response = {...xOrg, id: 1}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(response)); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateCreate({}, es, qc, e, aFn); + const res = decorateCreate({}, cache, e, aFn); res(xOrg).then((newX) => { expect(newX).to.equal(response); - expect(get(es, e, 1).value).to.deep.equal({...response, __ladda__id: 1}); + expect(getEntity(cache, e, 1).value).to.deep.equal({...response, __ladda__id: 1}); done(); }); }); diff --git a/src/plugins/cache/operations/delete.js b/src/plugins/cache/operations/delete.js index 4a51a36..7c7727a 100644 --- a/src/plugins/cache/operations/delete.js +++ b/src/plugins/cache/operations/delete.js @@ -1,12 +1,11 @@ import {passThrough} from 'ladda-fp'; -import {remove} from '../entity-store'; -import {invalidate} from '../query-cache'; +import * as Cache from '../cache'; import {serialize} from '../serializer'; -export function decorateDelete(c, es, qc, e, aFn) { +export function decorateDelete(c, cache, e, aFn) { return (...args) => { return aFn(...args) - .then(passThrough(() => invalidate(qc, e, aFn))) - .then(() => remove(es, e, serialize(args))); + .then(passThrough(() => Cache.invalidateQuery(cache, e, aFn))) + .then(() => Cache.removeEntity(cache, e, serialize(args))); }; } diff --git a/src/plugins/cache/operations/delete.spec.js b/src/plugins/cache/operations/delete.spec.js index fbd1702..85e98da 100644 --- a/src/plugins/cache/operations/delete.spec.js +++ b/src/plugins/cache/operations/delete.spec.js @@ -1,7 +1,6 @@ import sinon from 'sinon'; import {decorateDelete} from './delete'; -import {createEntityStore, get, put} from '../entity-store'; -import {createQueryCache} from '../query-cache'; +import * as Cache from '../cache'; import {addId} from '../id-helper'; import {createApiFunction} from '../test-helper'; @@ -42,16 +41,15 @@ const config = [ describe('Delete', () => { describe('decorateDelete', () => { it('Removes cache', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = Cache.createCache(config); const e = config[0]; const xOrg = {id: 1, name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve({})); const aFn = sinon.spy(aFnWithoutSpy); - put(es, e, addId({}, undefined, undefined, xOrg)); - const res = decorateDelete({}, es, qc, e, aFn); + Cache.storeEntity(cache, e, addId({}, undefined, undefined, xOrg)); + const res = decorateDelete({}, cache, e, aFn); res(1).then(() => { - expect(get(es, e, 1)).to.equal(undefined); + expect(Cache.getEntity(cache, e, 1)).to.equal(undefined); done(); }); }); diff --git a/src/plugins/cache/operations/no-operation.js b/src/plugins/cache/operations/no-operation.js index 55921f7..75cc5a5 100644 --- a/src/plugins/cache/operations/no-operation.js +++ b/src/plugins/cache/operations/no-operation.js @@ -1,9 +1,9 @@ import {passThrough} from 'ladda-fp'; -import {invalidate} from '../query-cache'; +import {invalidateQuery} from '../cache'; -export function decorateNoOperation(c, es, qc, e, aFn) { +export function decorateNoOperation(c, cache, e, aFn) { return (...args) => { return aFn(...args) - .then(passThrough(() => invalidate(qc, e, aFn))); + .then(passThrough(() => invalidateQuery(cache, e, aFn))); }; } diff --git a/src/plugins/cache/operations/no-operation.spec.js b/src/plugins/cache/operations/no-operation.spec.js index 7ca0237..398d500 100644 --- a/src/plugins/cache/operations/no-operation.spec.js +++ b/src/plugins/cache/operations/no-operation.spec.js @@ -2,52 +2,48 @@ import sinon from 'sinon'; import {decorateNoOperation} from './no-operation'; -import {createEntityStore} from '../entity-store'; -import {createQueryCache, contains, put} from '../query-cache'; +import * as Cache from '../cache'; import {createSampleConfig, createApiFunction} from '../test-helper'; const config = createSampleConfig(); describe('DecorateNoOperation', () => { it('Invalidates based on what is specified in the original function', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = Cache.createCache(config); const e = config[0]; const xOrg = {__ladda__id: 1, name: 'Kalle'}; const aFn = sinon.spy(() => Promise.resolve({})); const getUsers = () => Promise.resolve(xOrg); aFn.invalidates = ['getUsers']; - put(qc, e, getUsers, ['args'], xOrg); - const res = decorateNoOperation({}, es, qc, e, aFn); + Cache.storeQueryResponse(cache, e, getUsers, ['args'], xOrg); + const res = decorateNoOperation({}, cache, e, aFn); res(xOrg).then(() => { - const killedCache = !contains(qc, e, getUsers, ['args']); + const killedCache = !Cache.containsQueryResponse(cache, e, getUsers, ['args']); expect(killedCache).to.be.true; done(); }); }); it('Does not change original function', () => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = Cache.createCache(config); const e = config[0]; const aFn = sinon.spy(() => { return Promise.resolve({}); }); - decorateNoOperation({}, es, qc, e, aFn); + decorateNoOperation({}, cache, e, aFn); expect(aFn.operation).to.be.undefined; }); it('Ignored inherited invalidation config', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = Cache.createCache(config); const e = config[0]; const xOrg = {__ladda__id: 1, name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve({}), {invalidates: ['user']}); const aFn = sinon.spy(aFnWithoutSpy); const getUsers = createApiFunction(() => Promise.resolve(xOrg)); aFn.hasOwnProperty = () => false; - put(qc, e, getUsers, ['args'], xOrg); - const res = decorateNoOperation({}, es, qc, e, aFn); + Cache.storeQueryResponse(cache, e, getUsers, ['args'], xOrg); + const res = decorateNoOperation({}, cache, e, aFn); res(xOrg).then(() => { - const killedCache = !contains(qc, e, getUsers, ['args']); + const killedCache = !Cache.containsQueryResponse(cache, e, getUsers, ['args']); expect(killedCache).to.be.false; done(); }); diff --git a/src/plugins/cache/operations/read.js b/src/plugins/cache/operations/read.js index 126b7f7..045cbc1 100644 --- a/src/plugins/cache/operations/read.js +++ b/src/plugins/cache/operations/read.js @@ -1,13 +1,5 @@ import {passThrough, compose, curry, reduce, toIdMap, map, concat, zip} from 'ladda-fp'; -import {get as getFromEs, - put as putInEs, - mPut as mPutInEs, - contains as inEs} from '../entity-store'; -import {get as getFromQc, - invalidate, - put as putInQc, - contains as inQc, - getValue} from '../query-cache'; +import * as Cache from '../cache'; import {addId, removeId} from '../id-helper'; const getTtl = e => e.ttl * 1000; @@ -17,9 +9,9 @@ const hasExpired = (e, timestamp) => { return (Date.now() - timestamp) > getTtl(e); }; -const readFromCache = curry((es, e, aFn, id) => { - if (inEs(es, e, id) && !aFn.alwaysGetFreshData) { - const v = getFromEs(es, e, id); +const readFromCache = curry((cache, e, aFn, id) => { + if (Cache.containsEntity(cache, e, id) && !aFn.alwaysGetFreshData) { + const v = Cache.getEntity(cache, e, id); if (!hasExpired(e, v.timestamp)) { return removeId(v.value); } @@ -27,22 +19,22 @@ const readFromCache = curry((es, e, aFn, id) => { return undefined; }); -const decorateReadSingle = (c, es, qc, e, aFn) => { +const decorateReadSingle = (c, cache, e, aFn) => { return (id) => { - const fromCache = readFromCache(es, e, aFn, id); + const fromCache = readFromCache(cache, e, aFn, id); if (fromCache) { return Promise.resolve(fromCache); } return aFn(id) - .then(passThrough(compose(putInEs(es, e), addId(c, aFn, id)))) - .then(passThrough(() => invalidate(qc, e, aFn))); + .then(passThrough(compose(Cache.storeEntity(cache, e), addId(c, aFn, id)))) + .then(passThrough(() => Cache.invalidateQuery(cache, e, aFn))); }; }; -const decorateReadSome = (c, es, qc, e, aFn) => { +const decorateReadSome = (c, cache, e, aFn) => { return (ids) => { - const readFromCache_ = readFromCache(es, e, aFn); + const readFromCache_ = readFromCache(cache, e, aFn); const [cached, remaining] = reduce(([c_, r], id) => { const fromCache = readFromCache_(id); if (fromCache) { @@ -60,8 +52,8 @@ const decorateReadSome = (c, es, qc, e, aFn) => { const addIds = map(([id, item]) => addId(c, aFn, id, item)); return aFn(remaining) - .then(passThrough(compose(mPutInEs(es, e), addIds, zip(remaining)))) - .then(passThrough(() => invalidate(qc, e, aFn))) + .then(passThrough(compose(Cache.storeEntities(cache, e), addIds, zip(remaining)))) + .then(passThrough(() => Cache.invalidateQuery(cache, e, aFn))) .then((other) => { const asMap = compose(toIdMap, concat)(cached, other); return map((id) => asMap[id], ids); @@ -69,27 +61,29 @@ const decorateReadSome = (c, es, qc, e, aFn) => { }; }; -const decorateReadQuery = (c, es, qc, e, aFn) => { +const decorateReadQuery = (c, cache, e, aFn) => { return (...args) => { - if (inQc(qc, e, aFn, args) && !aFn.alwaysGetFreshData) { - const v = getFromQc(qc, e, aFn, args); + if (Cache.containsQueryResponse(cache, e, aFn, args) && !aFn.alwaysGetFreshData) { + const v = Cache.getQueryResponseWithMeta(cache, e, aFn, args); if (!hasExpired(e, v.timestamp)) { - return Promise.resolve(removeId(getValue(v.value))); + return Promise.resolve(removeId(Cache.getQueryResponse(v.value))); } } return aFn(...args) - .then(passThrough(compose(putInQc(qc, e, aFn, args), addId(c, aFn, args)))) - .then(passThrough(() => invalidate(qc, e, aFn))); + .then(passThrough( + compose(Cache.storeQueryResponse(cache, e, aFn, args), + addId(c, aFn, args)))) + .then(passThrough(() => Cache.invalidateQuery(cache, e, aFn))); }; }; -export function decorateRead(c, es, qc, e, aFn) { +export function decorateRead(c, cache, e, aFn) { if (aFn.byId) { - return decorateReadSingle(c, es, qc, e, aFn); + return decorateReadSingle(c, cache, e, aFn); } if (aFn.byIds) { - return decorateReadSome(c, es, qc, e, aFn); + return decorateReadSome(c, cache, e, aFn); } - return decorateReadQuery(c, es, qc, e, aFn); + return decorateReadQuery(c, cache, e, aFn); } diff --git a/src/plugins/cache/operations/read.spec.js b/src/plugins/cache/operations/read.spec.js index da6c182..b7193ac 100644 --- a/src/plugins/cache/operations/read.spec.js +++ b/src/plugins/cache/operations/read.spec.js @@ -3,8 +3,7 @@ import sinon from 'sinon'; import {map} from 'ladda-fp'; import {decorateRead} from './read'; -import {createEntityStore} from '../entity-store'; -import {createQueryCache} from '../query-cache'; +import {createCache} from '../cache'; import {createSampleConfig, createApiFunction} from '../test-helper'; const config = createSampleConfig(); @@ -12,39 +11,36 @@ const config = createSampleConfig(); describe('Read', () => { describe('decorateRead', () => { it('stores and returns an array with elements that lack id', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const xOrg = [{name: 'Kalle'}, {name: 'Anka'}]; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg), {idFrom: 'ARGS'}); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); res(1).then(x => { expect(x).to.deep.equal(xOrg); done(); }); }); it('does set id to serialized args if idFrom ARGS', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const xOrg = {name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg), {idFrom: 'ARGS'}); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); res({hello: 'hej', other: 'svej'}).then(x => { expect(x).to.deep.equal({name: 'Kalle'}); done(); }); }); it('calls api fn if not in cache with byId set', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const xOrg = {id: 1, name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg), {byId: true}); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); res(1).then(() => { expect(aFn.callCount).to.equal(1); done(); @@ -53,13 +49,12 @@ describe('Read', () => { it('calls api fn if in cache, but expired, with byId set', (done) => { const myConfig = createSampleConfig(); myConfig[0].ttl = 0; - const es = createEntityStore(myConfig); - const qc = createQueryCache(es); + const cache = createCache(myConfig); const e = myConfig[0]; const xOrg = {id: 1, name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg), {byId: true}); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); const delay = () => new Promise((resolve) => setTimeout(resolve, 1)); res(1).then(delay).then(res.bind(null, 1)).then(() => { expect(aFn.callCount).to.equal(2); @@ -67,13 +62,12 @@ describe('Read', () => { }); }); it('does not call api fn if in cache with byId set', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const xOrg = {id: 1, name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg), {byId: true}); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); res(1).then(res.bind(null, 1)).then(() => { expect(aFn.callCount).to.equal(1); done(); @@ -90,33 +84,30 @@ describe('Read', () => { const decoratedFn = createApiFunction(fn, { byIds: true }); it('calls api fn if nothing in cache', () => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const fnWithSpy = sinon.spy(decoratedFn); - const apiFn = decorateRead({}, es, qc, e, fnWithSpy); + const apiFn = decorateRead({}, cache, e, fnWithSpy); return apiFn(['a', 'b']).then((res) => { expect(res).to.deep.equal([users.a, users.b]); }); }); it('calls api fn if nothing in cache', () => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const fnWithSpy = sinon.spy(decoratedFn); - const apiFn = decorateRead({}, es, qc, e, fnWithSpy); + const apiFn = decorateRead({}, cache, e, fnWithSpy); return apiFn(['a', 'b']).then((res) => { expect(res).to.deep.equal([users.a, users.b]); }); }); it('puts item in the cache and can read them again', () => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const fnWithSpy = sinon.spy(decoratedFn); - const apiFn = decorateRead({}, es, qc, e, fnWithSpy); + const apiFn = decorateRead({}, cache, e, fnWithSpy); const args = ['a', 'b']; return apiFn(args).then(() => { return apiFn(args).then((res) => { @@ -127,11 +118,10 @@ describe('Read', () => { }); it('only makes additional request for uncached items', () => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const fnWithSpy = sinon.spy(decoratedFn); - const apiFn = decorateRead({}, es, qc, e, fnWithSpy); + const apiFn = decorateRead({}, cache, e, fnWithSpy); return apiFn(['a', 'b']).then(() => { return apiFn(['b', 'c']).then(() => { expect(fnWithSpy).to.have.been.calledTwice; @@ -142,11 +132,10 @@ describe('Read', () => { }); it('returns all items in correct order when making partial requests', () => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const fnWithSpy = sinon.spy(decoratedFn); - const apiFn = decorateRead({}, es, qc, e, fnWithSpy); + const apiFn = decorateRead({}, cache, e, fnWithSpy); return apiFn(['a', 'b']).then(() => { return apiFn(['a', 'b', 'c']).then((res) => { expect(res).to.deep.equal([users.a, users.b, users.c]); @@ -155,26 +144,24 @@ describe('Read', () => { }); }); it('calls api fn if not in cache', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const xOrg = {id: 1, name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg)); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); res(1).then(() => { expect(aFn.callCount).to.equal(1); done(); }); }); it('does not call api fn if in cache', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const xOrg = {id: 1, name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg)); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); const firstCall = res(1); @@ -186,13 +173,12 @@ describe('Read', () => { }); }); it('does call api fn if in cache but expired', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = {...config[0], ttl: -1}; const xOrg = {id: 1, name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg)); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); const firstCall = res(1); @@ -204,26 +190,24 @@ describe('Read', () => { }); }); it('calls api fn if not in cache (plural)', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const xOrg = [{id: 1, name: 'Kalle'}]; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg)); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); res(1).then((x) => { expect(x).to.equal(xOrg); done(); }); }); it('does not call api fn if in cache (plural)', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = config[0]; const xOrg = [{id: 1, name: 'Kalle'}]; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg)); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); const firstCall = res(1); @@ -235,13 +219,12 @@ describe('Read', () => { }); }); it('does call api fn if in cache but expired (plural)', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = {...config[0], ttl: -1}; const xOrg = [{id: 1, name: 'Kalle'}]; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg)); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); const firstCall = res(1); @@ -253,13 +236,12 @@ describe('Read', () => { }); }); it('throws if id is missing', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = createCache(config); const e = {...config[0], ttl: 300}; const xOrg = {name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg)); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateRead({}, es, qc, e, aFn); + const res = decorateRead({}, cache, e, aFn); res().catch(err => { expect(err).to.be.a('Error'); diff --git a/src/plugins/cache/operations/update.js b/src/plugins/cache/operations/update.js index 349ad78..0634f61 100644 --- a/src/plugins/cache/operations/update.js +++ b/src/plugins/cache/operations/update.js @@ -1,12 +1,11 @@ import {passThrough} from 'ladda-fp'; -import {put} from '../entity-store'; -import {invalidate} from '../query-cache'; +import * as Cache from '../cache'; import {addId} from '../id-helper'; -export function decorateUpdate(c, es, qc, e, aFn) { +export function decorateUpdate(c, cache, e, aFn) { return (eValue, ...args) => { return aFn(eValue, ...args) - .then(passThrough(() => invalidate(qc, e, aFn))) - .then(passThrough(() => put(es, e, addId(c, undefined, undefined, eValue)))); + .then(passThrough(() => Cache.invalidateQuery(cache, e, aFn))) + .then(passThrough(() => Cache.storeEntity(cache, e, addId(c, undefined, undefined, eValue)))); }; } diff --git a/src/plugins/cache/operations/update.spec.js b/src/plugins/cache/operations/update.spec.js index 0578b60..078f8b0 100644 --- a/src/plugins/cache/operations/update.spec.js +++ b/src/plugins/cache/operations/update.spec.js @@ -1,7 +1,6 @@ import sinon from 'sinon'; import {decorateUpdate} from './update'; -import {createEntityStore, get} from '../entity-store'; -import {createQueryCache} from '../query-cache'; +import * as Cache from '../cache'; import {createApiFunction} from '../test-helper'; const config = [ @@ -41,16 +40,15 @@ const config = [ describe('Update', () => { describe('decorateUpdate', () => { it('Updates cache based on argument', (done) => { - const es = createEntityStore(config); - const qc = createQueryCache(es); + const cache = Cache.createCache(config); const e = config[0]; const xOrg = {id: 1, name: 'Kalle'}; const aFnWithoutSpy = createApiFunction(() => Promise.resolve(xOrg)); const aFn = sinon.spy(aFnWithoutSpy); - const res = decorateUpdate({}, es, qc, e, aFn); + const res = decorateUpdate({}, cache, e, aFn); res(xOrg, 'other args').then(() => { - expect(get(es, e, 1).value).to.deep.equal({...xOrg, __ladda__id: 1}); + expect(Cache.getEntity(cache, e, 1).value).to.deep.equal({...xOrg, __ladda__id: 1}); done(); }); });