-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathindexed-db.js
More file actions
102 lines (90 loc) · 2.48 KB
/
Copy pathindexed-db.js
File metadata and controls
102 lines (90 loc) · 2.48 KB
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
//
// ImmortalDB - A resilient key-value store for browsers.
//
// Ansgar Grunseid
// grunseid.com
// grunseid@gmail.com
//
// License: MIT
//
import {
Store,
get as idbGet,
set as idbSet,
del as idbRemove,
} from 'idb-keyval'
const DEFAULT_DATABASE_NAME = 'ImmortalDB'
const DEFAULT_STORE_NAME = 'key-value-pairs'
const DEFAULT_EXPIRES_DB_NAME = 'ImmortalDBExp'
class IndexedDbStore {
constructor (
dbName = DEFAULT_DATABASE_NAME,
storeName = DEFAULT_STORE_NAME,
expiresDBName = DEFAULT_EXPIRES_DB_NAME,
) {
this.store = new Store(dbName, storeName)
this.expiresStore = new Store(expiresDBName, storeName)
return (async () => {
// Safari throws a SecurityError if IndexedDB.open() is called in a
// cross-origin iframe.
//
// SecurityError: IDBFactory.open() called in an invalid security context
//
// Catch such and fail gracefully.
//
// TODO(grun): Update idb-keyval's Store class to fail gracefully in
// Safari. Push the fix(es) upstream.
try {
await this.store._dbp
await this.expiresStore._dbp
} catch (err) {
if (err.name === 'SecurityError') {
return null // Failed to open an IndexedDB database.
} else {
throw err
}
}
return this
})()
}
async get (key) {
const val = await this.getExpires(key)
if (val && val <= new Date().getTime()) {
await this.remove(key)
}
const value = await idbGet(key, this.store)
return typeof value === 'string' ? value : undefined
}
async set (key, value, options = { expires: 0, isExpiresDate: false }) {
await idbSet(key, value, this.store)
if (options && options.expires) {
// If expire exists, update or add it.
await idbSet(
key,
options.isExpiresDate
? options.expires.toString()
: new Date(new Date().getTime() + options.expires * 60 * 1000)
.getTime()
.toString(),
this.expiresStore,
)
} else {
// If it doesn't exist, remove any existing expiration
await idbRemove(key, this.expiresStore)
}
}
async getExpires (key) {
const value = await idbGet(key, this.expiresStore)
return typeof value === 'string' ? +value : 0
}
async remove (key) {
await idbRemove(key, this.expiresStore)
await idbRemove(key, this.store)
}
}
export {
IndexedDbStore,
DEFAULT_DATABASE_NAME,
DEFAULT_STORE_NAME,
DEFAULT_EXPIRES_DB_NAME,
}