Skip to content

Commit

Permalink
Add support for modules
Browse files Browse the repository at this point in the history
  • Loading branch information
vencakrecl committed Nov 23, 2020
1 parent 69f24a0 commit b0a0ae8
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 52 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ Vue.use(Vuex);

const store = new Store({});

// create for every module
const cache = new VuexSimpleCache()

store.registerModule('test', {
state: {
items: [{ name: 'cache' }],
},
actions: {
testAction: cacheAction('items', ({ commit }) => { // cache data for 30 seconds
testAction: cache.cacheAction('items', ({ commit }) => { // cache data for 30 seconds
// call API
const data = [{ name: 'cache' }];

Expand All @@ -45,7 +48,7 @@ store.registerModule('test', {
})
```

### API - cacheAction
### API - VuexSimpleCache.cacheAction
* key - name of key from vuex state
* action - standard vuex action
* expiration - time in seconds
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@vencakrecl/vuex-simple-cache",
"author": "Venca Krecl <[email protected]>",
"description": "Simple cache for vuex action",
"version": "1.0.0-alpha.7",
"version": "1.0.0-alpha.8",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
82 changes: 44 additions & 38 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,57 @@
import { ActionContext } from 'vuex';

const expirations = new Map();

export const cacheAction = <S extends Record<string, any>, R>(
key: string,
action: (context: ActionContext<S, R>) => any,
expiration: number = 0
): any => {
return (context: ActionContext<S, R>) => {
if (!(key in context.state)) {
throw new Error(`Key "${key}" in state doesn't exist.`);
}

if (expiration > 0) {
const timestampKey: string = `__timestamp_${key}`;

if (expirations.has(timestampKey)) {
if (Date.now() - expiration > expirations.get(timestampKey)) {
expirations.delete(timestampKey);

return action(context);
class VuexSimpleCache {
private items: Map<string, number>;

constructor() {
this.items = new Map();
}

public cacheAction = <S extends Record<string, any>, R>(
key: string,
action: (context: ActionContext<S, R>) => any,
expiration: number = 0
): any => {
return (context: ActionContext<S, R>) => {
if (!(key in context.state)) {
throw new Error(`Key "${key}" in state doesn't exist.`);
}

if (expiration > 0) {
if (this.items.has(key)) {
if (Date.now() - expiration > (this.items.get(key) || 0)) {
this.items.delete(key);

return action(context);
}
} else {
this.items.set(key, Date.now());
}
} else {
expirations.set(timestampKey, Date.now());
}
}

if (Array.isArray(context.state[key])) {
if (context.state[key].length) {
return context.state[key];
if (Array.isArray(context.state[key])) {
if (context.state[key].length) {
return context.state[key];
}

return action(context);
}

return action(context);
}
if (context.state[key] instanceof Object) {
if (Object.keys(context.state[key]).length) {
return context.state[key];
}

return action(context);
}

if (context.state[key] instanceof Object) {
if (Object.keys(context.state[key]).length) {
if (context.state[key]) {
return context.state[key];
}

return action(context);
}

if (context.state[key]) {
return context.state[key];
}

return action(context);
};
};
};
}

export default VuexSimpleCache;
25 changes: 14 additions & 11 deletions test/cache.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Vue from 'vue';
import Vuex, { Store } from 'vuex';
import { cacheAction } from '../src';
import VuexSimpleCache from '../src';

Vue.use(Vuex);
const TEST_ACTION = 'TEST_ACTION';
Expand All @@ -10,6 +10,7 @@ const TEST_MUTATION_CACHE = 'TEST_CACHE';

describe('test vuex simple cache', () => {
it('cacheAction', async () => {
const cache = new VuexSimpleCache();
const state = {
string: 'test',
stringEmpty: '',
Expand All @@ -21,48 +22,48 @@ describe('test vuex simple cache', () => {
objectEmpty: {},
};

let res = cacheAction('string', () => {
let res = cache.cacheAction('string', () => {
expect(true).toBe(false);
})({ state });
expect(res).toStrictEqual('test');

res = cacheAction('stringEmpty', ({ state }) => {
res = cache.cacheAction('stringEmpty', ({ state }) => {
expect(state.stringEmpty).toBe('');

return 'test';
})({ state });
expect(res).toStrictEqual('test');

res = cacheAction('number', () => {
res = cache.cacheAction('number', () => {
expect(true).toBe(false);
})({ state });
expect(res).toStrictEqual(5);

res = cacheAction('numberEmpty', () => {
res = cache.cacheAction('numberEmpty', () => {
expect(state.numberEmpty).toBe(0);

return 5;
})({ state });
expect(res).toStrictEqual(5);

res = cacheAction('array', () => {
res = cache.cacheAction('array', () => {
expect(true).toBe(false);
})({ state });
expect(res).toStrictEqual([1]);

res = cacheAction('arrayEmpty', () => {
res = cache.cacheAction('arrayEmpty', () => {
expect(state.arrayEmpty).toStrictEqual([]);

return [1];
})({ state });
expect(res).toStrictEqual([1]);

res = cacheAction('object', () => {
res = cache.cacheAction('object', () => {
expect(true).toBe(false);
})({ state });
expect(res).toStrictEqual({ 1: 1 });

res = cacheAction('objectEmpty', () => {
res = cache.cacheAction('objectEmpty', () => {
expect(state.objectEmpty).toStrictEqual({});

return { 1: 1 };
Expand All @@ -71,6 +72,7 @@ describe('test vuex simple cache', () => {
});

it('vuex', async () => {
const cache = new VuexSimpleCache();
const store = new Store({});

store.registerModule('test', {
Expand All @@ -87,7 +89,7 @@ describe('test vuex simple cache', () => {

return data;
},
[TEST_ACTION_CACHE]: cacheAction('itemsCache', ({ commit }) => {
[TEST_ACTION_CACHE]: cache.cacheAction('itemsCache', ({ commit }) => {
// call API
const data = [{ name: 'cache' }];

Expand Down Expand Up @@ -121,14 +123,15 @@ describe('test vuex simple cache', () => {
});

it('expiration', async () => {
const cache = new VuexSimpleCache();
const store = new Store({});

store.registerModule('test', {
state: {
items: [{ name: 'cache' }],
},
actions: {
[TEST_ACTION_CACHE]: cacheAction(
[TEST_ACTION_CACHE]: cache.cacheAction(
'items',
() => {
// call API
Expand Down

0 comments on commit b0a0ae8

Please sign in to comment.