This repository has been archived by the owner on Feb 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 108
/
cache.js
112 lines (80 loc) · 2.73 KB
/
cache.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import isString from 'lodash/isString'
import isFunction from 'lodash/isFunction'
import map from 'lodash/map'
import serialize from './serialize'
async function write (config, req, res) {
try {
const entry = {
expires: config.expires,
data: serialize(config, req, res)
}
await config.store.setItem(config.uuid, entry)
} catch (err) {
config.debug('Could not store response', err)
if (config.clearOnError) {
try {
await config.store.clear()
} catch (err) {
config.debug('Could not clear store', err)
}
}
return false
}
return true
}
async function read (config, req) {
const { uuid } = config
const entry = await config.store.getItem(uuid)
if (!entry || !entry.data) {
config.debug('cache-miss', req.url)
const error = new Error()
error.reason = 'cache-miss'
error.message = 'Entry not found from cache'
throw error
}
const { expires, data } = entry
// Do not check for stale cache if offline on client-side
const offline = typeof navigator !== 'undefined' && 'onLine' in navigator && !navigator.onLine
if (!offline && !config.acceptStale && expires !== 0 && (expires < Date.now())) {
config.debug('cache-stale', req.url)
const error = new Error()
error.reason = 'cache-stale'
error.message = 'Entry is stale'
throw error
}
config.debug(config.acceptStale ? 'cache-hit-stale' : 'cache-hit', req.url)
return data
}
function key (config) {
if (isFunction(config.key)) return config.key
let cacheKey
if (isString(config.key)) cacheKey = req => `${config.key}/${req.url}${serializeQuery(req)}`
else cacheKey = req => req.url + serializeQuery(req)
return cacheKey
}
async function defaultInvalidate (cfg, req) {
const method = req.method.toLowerCase()
if (method !== 'get') {
await cfg.store.removeItem(cfg.uuid)
}
}
function invalidate (config = {}) {
if (isFunction(config.invalidate)) return config.invalidate
return defaultInvalidate
}
function serializeQuery (req) {
if (!req.params) return ''
// Probably server-side, just stringify the object
if (typeof URLSearchParams === 'undefined') return JSON.stringify(req.params)
const isInstanceOfURLSearchParams = req.params instanceof URLSearchParams
// Convert to an instance of URLSearchParams so it get serialized the same way
if (!isInstanceOfURLSearchParams) {
const params = req.params
req.params = new URLSearchParams()
// Using lodash/map even though we don't listen to output so we don't have to bundle lodash/forEach
map(params, (value, key) => req.params.append(key, value))
}
return `?${req.params.toString()}`
}
export { read, write, key, invalidate }
export default { read, write, key, invalidate }