Skip to content

Commit 8078fce

Browse files
committed
fixes
1 parent 6a3f991 commit 8078fce

File tree

5 files changed

+121
-60
lines changed

5 files changed

+121
-60
lines changed

README.md

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,37 @@ npm install --save cache-api-keyval
2020
<script src="/cache-api-keyval.js"></script>
2121
<script>
2222
23-
// optional: wait for async browser check to complete
24-
// the test checks if Cache API is blocked by privacy or cookie settings
25-
// the callback is not required if you initiate the database sufficient time after the cache-api-keyval.js script is loaded
26-
onCacheApiDB(function() {
23+
// load database
24+
var db = new CacheApiDB('my-store', { namespace: 'optional' });
25+
26+
// set JSON object data
27+
db.set('key', { json: 'object' });
2728
28-
// load database
29-
var db = new CacheApiDB('my-store', { namespace: 'optional' });
29+
// set text data with expiration in 24 hours
30+
db.set('key2', 'string', 86400);
3031
31-
if (db.supported) { // Cache API supported by browser
32+
// get data from cache
33+
db.get('key').then(function(json) {
34+
console.log('json object', json);
35+
});
3236
33-
// set JSON object data
34-
db.set('key', { json: 'object' });
37+
// delete key from database
38+
db.del('key2');
3539
36-
// set text data with expiration in 24 hours
37-
db.set('key2', 'string', 86400);
40+
// prune expired cache entries
41+
db.prune();
3842
39-
// get data from cache
40-
db.get('key').then(function(json) {
41-
console.log('json object', json);
42-
});
43+
// if no fallback is provided, all methods will reject and the constructor will contain `no` with integer 1.
44+
if (db.no === 1) { // === 1 is optional
45+
// Cache API is not supported by the browser
46+
}
4347
44-
// delete key from database
45-
db.del('key2');
48+
// optional: wait for async browser check to complete
49+
// the test checks if Cache API is blocked by privacy or cookie settings
50+
// when blocked, the fallback storage is loaded
51+
onCacheApiDB(function() {
4652
47-
// prune expired cache entries
48-
db.prune();
49-
}
53+
/* initiate database with certain availability */
5054
5155
});
5256
</script>

cache-api-keyval.ext.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,31 @@ window.CacheApiDB = global.CacheApiDB = this.CacheApiDB = self.CacheApiDB = wind
77
options.namespace = '';
88

99
return {
10-
supported: false,
10+
no: 1,
1111
get: function() {},
1212
set: function() {},
1313
del: function() {},
1414
prune: function() {}
1515
}
1616
}
1717

18+
function CACHE(store, options) {
19+
this.no = 1;
20+
}
21+
22+
23+
// public get method
24+
CACHE.prototype.get = function(key) {}
25+
26+
// public set method
27+
CACHE.prototype.set = function(key, value, expire) {}
28+
29+
// public delete method
30+
CACHE.prototype.del = function(key) {}
31+
32+
// public cache prune method
33+
CACHE.prototype.prune = function() {}
34+
1835
var cache_headers = {
1936
"x-date": '',
2037
"x-expire": '',

dist/cache-api-keyval.js

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"name": "cache-api-keyval",
3-
"version": "1.0.6",
3+
"version": "1.0.8",
44
"description": "Browser Cache API key/value store with +50MB capacity, expiration and JSON object data-type storage.",
55
"author": {
66
"name": "info@optimization.team",
77
"email": "info@optimization.team",
88
"web": "optimization.team"
99
},
10-
"keywords": ["Cache", "IndexedDB", "Cache API", "CacheStorage", "keyvalue", "keyval", "key/value"],
10+
"keywords": ["Cache", "IndexedDB", "Cache API", "CacheStorage", "keyvalue", "keyval", "key/value", "localstorage"],
1111
"homepage": "https://github.com/optimalisatie/",
1212
"copyright": "Copyright (C) 2018 Optimization.Team, Utrecht, NLD",
1313
"main": "cache-api-keyval.js",

src/cache-api-keyval.js

Lines changed: 72 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@
2525
}
2626

2727
// set cache api db controller
28-
function setCacheApiDB(factory) {
28+
function setCacheApiDB(fallbackFactory) {
2929

30-
_root.CacheApiDB = factory;
30+
// set fallback
31+
if (fallbackFactory) {
32+
_root.CacheApiDB = fallbackFactory;
33+
}
3134

3235
// process callback queue
3336
var callback = queue.shift();
@@ -36,12 +39,12 @@
3639
}
3740
}
3841

39-
var nosupport_error = 'Browser does not support Cache API';
42+
var nosupport_error = 'No Cache API';
4043

4144
if (!_root.CacheApiDBFallback) {
4245
_root.CacheApiDBFallback = function() {
4346
var that = this;
44-
that.supported = 0;
47+
that.no = 1;
4548
['get', 'set', 'del', 'prune'].forEach(function(method) {
4649
that[method] = function() {
4750
return Promise.reject(nosupport_error);
@@ -56,24 +59,31 @@
5659
_root.CacheApiDB = _root.CacheApiDBFallback;
5760
} else {
5861

59-
// test cache support
60-
// Cache API could be blocked by browser privacy settings
62+
// enable instant usage of Cache API store
63+
_root.CacheApiDB = factory();
64+
65+
// test if Cache API is blocked by browser privacy settings
6166
caches.open('x').catch(function(e) {
62-
if (e.name == 'SecurityError') {
63-
print_error('Cache API is blocked by browser. Please check privacy settings (cookies, no-track option etc).');
64-
} else {
65-
print_error('Cache API error: ' + e.message);
67+
68+
// report errors unrelated to privacy settings
69+
if (e.name != 'SecurityError') {
70+
print_error('Cache API: ' + e.message);
6671
}
72+
73+
// fallback
6774
setCacheApiDB(_root.CacheApiDBFallback);
75+
6876
}).then(function() {
69-
setCacheApiDB(factory());
77+
78+
// continue with Cache API
79+
setCacheApiDB();
7080
})
7181

7282
}
7383
})(function() {
7484

75-
var DATE_HEADER = 'x-date';
76-
var EXPIRE_HEADER = 'x-expire';
85+
var DATE_HEADER = 'x-d';
86+
var EXPIRE_HEADER = 'x-e';
7787
var CONTENT_TYPE_HEADER = 'Content-Type';
7888

7989
// return timestamp
@@ -95,12 +105,16 @@
95105
function CACHE_GET(store, key) {
96106
return CACHE_OPEN(store, function(cache) {
97107

108+
if (IS_UNDEFINED(key)) {
109+
ERROR();
110+
}
111+
98112
var cache_key = CACHE_KEY(key);
99113

100114
return cache.match(cache_key).then(function(cachedata) {
101115

102116
// handle expiration
103-
if (!cachedata || CACHE_EXPIRED(cachedata)) {
117+
if (!cachedata || CACHE_EXPIRED(store, cache_key, cachedata, 1)) {
104118
return false;
105119
}
106120

@@ -114,22 +128,27 @@
114128
function CACHE_SET(store, key, data, expire) {
115129
return CACHE_OPEN(store, function(cache) {
116130

131+
if (IS_UNDEFINED(key) || IS_UNDEFINED(data)) {
132+
ERROR();
133+
}
134+
117135
var cache_key = CACHE_KEY(key);
118136

119137
var cache_headers = {};
120138

121-
// cache date
122-
cache_headers[DATE_HEADER] = NOW();
123-
124139
// JSON
125140
cache_headers[CONTENT_TYPE_HEADER] = 'application/json';
126141
data = JSON.stringify(data);
127142

128143
// expire time
129144
if (expire) {
130-
expire = parseInt(expire);
145+
146+
// cache date
147+
cache_headers[DATE_HEADER] = NOW();
148+
149+
expire = INT(expire);
131150
if (isNaN(expire) || expire < 0) {
132-
ERROR('Expire time not numeric');
151+
ERROR();
133152
}
134153
cache_headers[EXPIRE_HEADER] = STRING(expire);
135154
}
@@ -144,30 +163,36 @@
144163
}
145164

146165
// return cache expired state
147-
function CACHE_EXPIRED(cachedata) {
166+
function CACHE_EXPIRED(store, cache_key, cachedata) {
148167
var exp = cachedata.headers.get(EXPIRE_HEADER);
149-
if (exp) {
150-
151-
var date = cachedata.headers.get(DATE_HEADER);
168+
var date = cachedata.headers.get(DATE_HEADER);
169+
if (exp && date) {
170+
exp = INT(exp);
171+
date = INT(date);
152172

153173
// expired
154174
if ((date + exp) < NOW()) {
155-
CACHE_DELETE(store, key);
175+
CACHE_DELETE(store, cache_key, 1);
156176
return true;
157177
}
158178
}
159179
}
160180

161181
// set key in cache
162-
function CACHE_DELETE(store, key) {
182+
function CACHE_DELETE(store, key, cache_key) {
163183
return CACHE_OPEN(store, function(cache) {
164-
var cache_key = CACHE_KEY(key);
165-
return cache.delete(cache_key);
184+
185+
if (IS_UNDEFINED(key)) {
186+
ERROR();
187+
}
188+
189+
key = (cache_key) ? key : CACHE_KEY(key);
190+
return cache.delete(key);
166191
});
167192
}
168193

169194
// set key in cache
170-
function CACHE_PRUNE(store, key) {
195+
function CACHE_PRUNE(store) {
171196
return CACHE_OPEN(store, function(cache) {
172197

173198
// get all keys from store
@@ -188,7 +213,7 @@
188213
cacheEntries.forEach(function(cachedata, key) {
189214

190215
// run expired check, auto-deletes expired entry
191-
CACHE_EXPIRED(cachedata);
216+
CACHE_EXPIRED(store, key, cachedata);
192217
});
193218
});
194219
});
@@ -200,7 +225,6 @@
200225
var that = this;
201226
if (that instanceof CACHE) {
202227
that.store = store;
203-
that.supported = 1;
204228

205229
if (IS_OBJECT(options)) {
206230
if (options.namespace) {
@@ -224,14 +248,29 @@
224248
return str.toString();
225249
}
226250

251+
// return INTEGER
252+
function INT(num) {
253+
return parseInt(num);
254+
}
255+
256+
// type check
257+
function IS(obj, type) {
258+
return typeof obj === type;
259+
}
260+
227261
// detect if object
228262
function IS_OBJECT(obj) {
229-
return typeof obj == 'object';
263+
return IS(obj, 'object');
264+
}
265+
266+
// detect if undefined
267+
function IS_UNDEFINED(obj) {
268+
return IS(obj, 'undefined');
230269
}
231270

232271
// output error
233272
function ERROR(msg) {
234-
throw new Error(msg);
273+
throw new Error(msg || 'input');
235274
}
236275

237276
// public get method
@@ -241,7 +280,7 @@
241280

242281
// public set method
243282
CACHE.prototype.set = function(key, value, expire) {
244-
return CACHE_SET(this.store, NAMESPACE(this.ns, key), value);
283+
return CACHE_SET(this.store, NAMESPACE(this.ns, key), value, expire);
245284
}
246285

247286
// public delete method

0 commit comments

Comments
 (0)