0
# Browser Storage
1
2
Browser storage adapters and presets for localStorage and sessionStorage integration. These adapters provide seamless integration with browser storage APIs while maintaining the same lowdb interface for consistent data management across environments.
3
4
## Capabilities
5
6
### Browser Storage Presets
7
8
Pre-configured database instances with browser storage adapters for immediate use.
9
10
```typescript { .api }
11
/**
12
* Create a LowSync instance with LocalStorage adapter for persistent browser storage
13
* @param key - Storage key for localStorage
14
* @param defaultData - Default data structure
15
* @returns Configured LowSync instance with data pre-loaded from localStorage
16
*/
17
function LocalStoragePreset<Data>(key: string, defaultData: Data): LowSync<Data>;
18
19
/**
20
* Create a LowSync instance with SessionStorage adapter for session-only browser storage
21
* @param key - Storage key for sessionStorage
22
* @param defaultData - Default data structure
23
* @returns Configured LowSync instance with data pre-loaded from sessionStorage
24
*/
25
function SessionStoragePreset<Data>(key: string, defaultData: Data): LowSync<Data>;
26
```
27
28
**Usage Examples:**
29
30
```typescript
31
import { LocalStoragePreset, SessionStoragePreset } from "lowdb/browser";
32
33
// Persistent storage across browser sessions
34
type AppData = {
35
user: { id: number; name: string; preferences: object };
36
settings: { theme: string; language: string };
37
};
38
39
const defaultData: AppData = {
40
user: { id: 0, name: "", preferences: {} },
41
settings: { theme: "light", language: "en" }
42
};
43
44
const db = LocalStoragePreset("myapp-data", defaultData);
45
46
// Update user preferences
47
db.update((data) => {
48
data.user.name = "Alice";
49
data.settings.theme = "dark";
50
});
51
52
// Session-only storage (cleared when tab closes)
53
const sessionDb = SessionStoragePreset("session-data", { cart: [] });
54
sessionDb.update(({ cart }) => cart.push({ id: 1, name: "Product" }));
55
```
56
57
### LocalStorage Adapter
58
59
Synchronous adapter for browser localStorage with automatic JSON serialization.
60
61
```typescript { .api }
62
/**
63
* Sync adapter for browser localStorage with automatic JSON parsing/stringifying
64
* @template T - The type of data stored in localStorage
65
*/
66
class LocalStorage<T> implements SyncAdapter<T> {
67
constructor(key: string);
68
69
/** Read and parse data from localStorage, returns null if key doesn't exist */
70
read(): T | null;
71
72
/** Stringify and store data in localStorage */
73
write(obj: T): void;
74
}
75
```
76
77
**Usage Examples:**
78
79
```typescript
80
import { LowSync } from "lowdb";
81
import { LocalStorage } from "lowdb/browser";
82
83
// Direct adapter usage
84
const adapter = new LocalStorage<{ count: number }>("app-counter");
85
const db = new LowSync(adapter, { count: 0 });
86
87
// Initialize from localStorage
88
db.read();
89
90
// Update and persist
91
db.data.count++;
92
db.write(); // Immediately saved to localStorage
93
94
// Data persists across browser sessions
95
console.log(localStorage.getItem("app-counter")); // {"count":1}
96
```
97
98
### SessionStorage Adapter
99
100
Synchronous adapter for browser sessionStorage with automatic JSON serialization.
101
102
```typescript { .api }
103
/**
104
* Sync adapter for browser sessionStorage with automatic JSON parsing/stringifying
105
* @template T - The type of data stored in sessionStorage
106
*/
107
class SessionStorage<T> implements SyncAdapter<T> {
108
constructor(key: string);
109
110
/** Read and parse data from sessionStorage, returns null if key doesn't exist */
111
read(): T | null;
112
113
/** Stringify and store data in sessionStorage */
114
write(obj: T): void;
115
}
116
```
117
118
**Usage Examples:**
119
120
```typescript
121
import { LowSync } from "lowdb";
122
import { SessionStorage } from "lowdb/browser";
123
124
// Session-only storage
125
const adapter = new SessionStorage<string[]>("temp-notes");
126
const notesDb = new LowSync(adapter, []);
127
128
notesDb.read();
129
notesDb.data.push("Temporary note");
130
notesDb.write(); // Saved to sessionStorage
131
132
// Data is cleared when tab closes
133
console.log(sessionStorage.getItem("temp-notes")); // ["Temporary note"]
134
```
135
136
### WebStorage Base Class
137
138
Base class for browser storage adapters (not directly exported, but used internally).
139
140
```typescript { .api }
141
/**
142
* Base sync adapter for browser storage APIs (localStorage/sessionStorage)
143
* @template T - The type of data stored
144
*/
145
class WebStorage<T> implements SyncAdapter<T> {
146
constructor(key: string, storage: Storage);
147
148
/** Read and parse JSON from storage, returns null if key doesn't exist */
149
read(): T | null;
150
151
/** Stringify and store JSON in storage */
152
write(obj: T): void;
153
}
154
```
155
156
## Browser-Specific Behavior
157
158
### Storage Persistence
159
160
**LocalStorage**:
161
- Data persists across browser sessions
162
- Survives page reloads and browser restarts
163
- Shared across all tabs/windows of the same origin
164
- Typically limited to 5-10MB per origin
165
166
**SessionStorage**:
167
- Data persists only for the current browser tab/window session
168
- Cleared when tab is closed
169
- Isolated per tab (not shared between tabs)
170
- Same storage limits as localStorage
171
172
### Storage Quotas
173
174
Browser storage has size limitations:
175
176
```typescript
177
import { LocalStoragePreset } from "lowdb/browser";
178
179
try {
180
const db = LocalStoragePreset("large-dataset", { data: [] });
181
182
// Add large amounts of data
183
db.update(({ data }) => {
184
for (let i = 0; i < 100000; i++) {
185
data.push({ id: i, content: "Large content string..." });
186
}
187
});
188
} catch (error) {
189
if (error.name === "QuotaExceededError") {
190
console.error("Storage quota exceeded");
191
// Handle storage limit reached
192
}
193
}
194
```
195
196
### Cross-Origin Restrictions
197
198
Storage is isolated by origin (protocol + domain + port):
199
200
```typescript
201
// Each origin has separate storage
202
// https://app.example.com - separate storage
203
// https://api.example.com - separate storage
204
// http://app.example.com - separate storage
205
206
const db = LocalStoragePreset("shared-data", {});
207
// This data is only accessible from the current origin
208
```
209
210
## Data Synchronization
211
212
### Multiple Tabs
213
214
LocalStorage data is shared between tabs and can be synchronized:
215
216
```typescript
217
import { LocalStoragePreset } from "lowdb/browser";
218
219
const db = LocalStoragePreset("shared-state", { count: 0 });
220
221
// Listen for storage changes from other tabs
222
window.addEventListener("storage", (event) => {
223
if (event.key === "shared-state" && event.newValue) {
224
// Reload data when changed by another tab
225
db.read();
226
console.log("Data updated by another tab:", db.data);
227
}
228
});
229
230
// Update data (will trigger storage event in other tabs)
231
db.update((data) => {
232
data.count++;
233
});
234
```
235
236
### React Integration
237
238
Example integration with React for reactive updates:
239
240
```typescript
241
import { useEffect, useState } from "react";
242
import { LocalStoragePreset } from "lowdb/browser";
243
244
function useLocalStorageDb<T>(key: string, defaultData: T) {
245
const [db] = useState(() => LocalStoragePreset(key, defaultData));
246
const [data, setData] = useState(db.data);
247
248
useEffect(() => {
249
const handleStorageChange = (event: StorageEvent) => {
250
if (event.key === key) {
251
db.read();
252
setData({ ...db.data });
253
}
254
};
255
256
window.addEventListener("storage", handleStorageChange);
257
return () => window.removeEventListener("storage", handleStorageChange);
258
}, [db, key]);
259
260
const updateData = (updater: (data: T) => void) => {
261
db.update(updater);
262
setData({ ...db.data });
263
};
264
265
return [data, updateData] as const;
266
}
267
268
// Usage in component
269
function App() {
270
const [data, updateData] = useLocalStorageDb("app-data", { todos: [] });
271
272
const addTodo = (todo: string) => {
273
updateData((data) => {
274
data.todos.push({ id: Date.now(), text: todo, done: false });
275
});
276
};
277
278
return <div>{/* Component JSX */}</div>;
279
}
280
```
281
282
## Error Handling
283
284
Browser storage adapters may encounter various errors:
285
286
```typescript
287
import { LocalStoragePreset } from "lowdb/browser";
288
289
try {
290
const db = LocalStoragePreset("my-data", { items: [] });
291
292
db.update(({ items }) => {
293
// Add large object that might exceed quota
294
items.push({ id: 1, largeData: "...".repeat(1000000) });
295
});
296
} catch (error) {
297
// Handle different storage errors
298
switch (error.name) {
299
case "QuotaExceededError":
300
console.error("Storage quota exceeded");
301
// Could implement cleanup or user notification
302
break;
303
case "SecurityError":
304
console.error("Storage access denied (private browsing?)");
305
break;
306
default:
307
console.error("Storage error:", error);
308
}
309
}
310
311
// Handle JSON parsing errors for corrupted data
312
try {
313
const db = LocalStoragePreset("potentially-corrupted", {});
314
db.read(); // Might fail if localStorage contains invalid JSON
315
} catch (error) {
316
if (error instanceof SyntaxError) {
317
console.error("Corrupted data in localStorage");
318
// Could clear corrupted data and reinitialize
319
localStorage.removeItem("potentially-corrupted");
320
}
321
}
322
```
323
324
## Performance Considerations
325
326
### Synchronous Operations
327
328
Browser storage adapters are synchronous and may block the main thread:
329
330
```typescript
331
// For large datasets, consider batching updates
332
const db = LocalStoragePreset("large-dataset", { items: [] });
333
334
// Instead of multiple individual updates
335
// for (let i = 0; i < 1000; i++) {
336
// db.update(({ items }) => items.push({ id: i })); // 1000 storage writes
337
// }
338
339
// Use single batch update
340
db.update(({ items }) => {
341
for (let i = 0; i < 1000; i++) {
342
items.push({ id: i });
343
}
344
}); // 1 storage write
345
```
346
347
### Memory Usage
348
349
Browser storage loads all data into memory. For large datasets:
350
351
- Consider data pagination or lazy loading
352
- Implement data cleanup strategies
353
- Use IndexedDB for larger datasets (via custom adapters)
354
355
### Private Browsing Mode
356
357
Some browsers restrict storage in private/incognito mode:
358
359
```typescript
360
function isStorageAvailable() {
361
try {
362
const test = "__storage_test__";
363
localStorage.setItem(test, test);
364
localStorage.removeItem(test);
365
return true;
366
} catch {
367
return false;
368
}
369
}
370
371
if (isStorageAvailable()) {
372
const db = LocalStoragePreset("app-data", {});
373
} else {
374
// Fallback to memory storage
375
const db = new LowSync(new MemorySync(), {});
376
}
377
```
378
379
## Browser Compatibility
380
381
Browser storage adapters work in all modern browsers that support:
382
383
- **localStorage/sessionStorage APIs** (IE8+, all modern browsers)
384
- **JSON.parse/JSON.stringify** (IE8+, all modern browsers)
385
- **ES6 Classes and Modules** (modern browsers or with transpilation)
386
387
For older browser support, ensure your build process includes appropriate polyfills and transpilation.