UNPKG

6.41 kBMarkdownView Raw
1# IDB-Keyval
2
3[![npm](https://img.shields.io/npm/v/idb-keyval.svg)](https://www.npmjs.com/package/idb-keyval)
4
5This is a super-simple promise-based keyval store implemented with IndexedDB, originally based on [async-storage by Mozilla](https://github.com/mozilla-b2g/gaia/blob/master/shared/js/async_storage.js).
6
7It's small and tree-shakeable. If you only use get/set, the library is ~370 bytes (brotli'd), if you use all methods it's ~570 bytes.
8
9Although this is tiny, it's a little larger than previous versions due to a [massive bug in Safari](https://bugs.webkit.org/show_bug.cgi?id=226547). Hopefully this fix can be removed in the not-too-distant future, when a version of Safari without the bug reaches enough users.
10
11[localForage](https://github.com/localForage/localForage) offers similar functionality, but supports older browsers with broken/absent IDB implementations. Because of that, it's orders of magnitude bigger (~7k).
12
13This is only a keyval store. If you need to do more complex things like iteration & indexing, check out [IDB on NPM](https://www.npmjs.com/package/idb) (a little heavier at 1k). The first example in its README is how to create a keyval store.
14
15## Installing
16
17### Recommended: Via npm + webpack/rollup/parcel/etc
18
19```sh
20npm install idb-keyval
21```
22
23Now you can require/import `idb-keyval`:
24
25```js
26import { get, set } from 'idb-keyval';
27```
28
29If you're targeting IE10/11, use the compat version, and import a `Promise` polyfill.
30
31```js
32// Import a Promise polyfill
33import 'es6-promise/auto';
34import { get, set } from 'idb-keyval/dist/esm-compat';
35```
36
37### All bundles
38
39A well-behaved bundler should automatically pick the ES module or the CJS module depending on what it supports, but if you need to force it either way:
40
41- `idb-keyval/dist/index.js` EcmaScript module.
42- `idb-keyval/dist/index.cjs` CommonJS module.
43
44Legacy builds:
45
46- `idb-keyval/dist/compat.js` EcmaScript module, transpiled for older browsers.
47- `idb-keyval/dist/compat.cjs` CommonJS module, transpiled for older browsers.
48- `idb-keyval/dist/umd.js` UMD module, also transpiled for older browsers.
49
50These built versions are also available on jsDelivr, e.g.:
51
52```html
53<script src="https://cdn.jsdelivr.net/npm/idb-keyval@6/dist/umd.js"></script>
54<!-- Or in modern browsers: -->
55<script type="module">
56 import { get, set } from 'https://cdn.jsdelivr.net/npm/idb-keyval@6/+esm';
57</script>
58```
59
60## Usage
61
62### set:
63
64```js
65import { set } from 'idb-keyval';
66
67set('hello', 'world');
68```
69
70Since this is IDB-backed, you can store anything structured-clonable (numbers, arrays, objects, dates, blobs etc), although old Edge doesn't support `null`. Keys can be numbers, strings, `Date`s, (IDB also allows arrays of those values, but IE doesn't support it).
71
72All methods return promises:
73
74```js
75import { set } from 'idb-keyval';
76
77set('hello', 'world')
78 .then(() => console.log('It worked!'))
79 .catch((err) => console.log('It failed!', err));
80```
81
82### get:
83
84```js
85import { get } from 'idb-keyval';
86
87// logs: "world"
88get('hello').then((val) => console.log(val));
89```
90
91If there is no 'hello' key, then `val` will be `undefined`.
92
93### setMany:
94
95Set many keyval pairs at once. This is faster than calling `set` multiple times.
96
97```js
98import { set, setMany } from 'idb-keyval';
99
100// Instead of:
101Promise.all([set(123, 456), set('hello', 'world')])
102 .then(() => console.log('It worked!'))
103 .catch((err) => console.log('It failed!', err));
104
105// It's faster to do:
106setMany([
107 [123, 456],
108 ['hello', 'world'],
109])
110 .then(() => console.log('It worked!'))
111 .catch((err) => console.log('It failed!', err));
112```
113
114This operation is also atomic – if one of the pairs can't be added, none will be added.
115
116### getMany:
117
118Get many keys at once. This is faster than calling `get` multiple times. Resolves with an array of values.
119
120```js
121import { get, getMany } from 'idb-keyval';
122
123// Instead of:
124Promise.all([get(123), get('hello')]).then(([firstVal, secondVal]) =>
125 console.log(firstVal, secondVal),
126);
127
128// It's faster to do:
129getMany([123, 'hello']).then(([firstVal, secondVal]) =>
130 console.log(firstVal, secondVal),
131);
132```
133
134### update:
135
136Transforming a value (eg incrementing a number) using `get` and `set` is risky, as both `get` and `set` are async and non-atomic:
137
138```js
139// Don't do this:
140import { get, set } from 'idb-keyval';
141
142get('counter').then((val) =>
143 set('counter', (val || 0) + 1);
144);
145
146get('counter').then((val) =>
147 set('counter', (val || 0) + 1);
148);
149```
150
151With the above, both `get` operations will complete first, each returning `undefined`, then each set operation will be setting `1`. You could fix the above by queuing the second `get` on the first `set`, but that isn't always feasible across multiple pieces of code. Instead:
152
153```js
154// Instead:
155import { update } from 'idb-keyval';
156
157update('counter', (val) => (val || 0) + 1);
158update('counter', (val) => (val || 0) + 1);
159```
160
161This will queue the updates automatically, so the first `update` set the `counter` to `1`, and the second `update` sets it to `2`.
162
163### del:
164
165Delete a particular key from the store.
166
167```js
168import { del } from 'idb-keyval';
169
170del('hello');
171```
172
173### delMany:
174
175Delete many keys at once. This is faster than calling `del` multiple times.
176
177```js
178import { del, delMany } from 'idb-keyval';
179
180// Instead of:
181Promise.all([del(123), del('hello')])
182 .then(() => console.log('It worked!'))
183 .catch((err) => console.log('It failed!', err));
184
185// It's faster to do:
186delMany([123, 'hello'])
187 .then(() => console.log('It worked!'))
188 .catch((err) => console.log('It failed!', err));
189```
190
191### clear:
192
193Clear all values in the store.
194
195```js
196import { clear } from 'idb-keyval';
197
198clear();
199```
200
201### entries:
202
203Get all entries in the store. Each entry is an array of `[key, value]`.
204
205```js
206import { entries } from 'idb-keyval';
207
208// logs: [[123, 456], ['hello', 'world']]
209entries().then((entries) => console.log(entries));
210```
211
212### keys:
213
214Get all keys in the store.
215
216```js
217import { keys } from 'idb-keyval';
218
219// logs: [123, 'hello']
220keys().then((keys) => console.log(keys));
221```
222
223### values:
224
225Get all values in the store.
226
227```js
228import { values } from 'idb-keyval';
229
230// logs: [456, 'world']
231values().then((values) => console.log(values));
232```
233
234### Custom stores:
235
236By default, the methods above use an IndexedDB database named `keyval-store` and an object store named `keyval`. If you want to use something different, see [custom stores](./custom-stores.md).