deepbase-json 3.1.8 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +533 -80
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,140 +1,593 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 🌳 DeepBase v3.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**The ultimate multi-driver persistence system for Node.js**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
DeepBase is a powerful, flexible database abstraction that lets you use multiple storage backends with a single, intuitive API. Write once, persist everywhere.
|
|
6
|
+
|
|
7
|
+
## ✨ What's New in v3.0
|
|
8
|
+
|
|
9
|
+
- 🔌 **Driver-based architecture**: Plug and play different storage backends
|
|
10
|
+
- 🔄 **Multi-driver support**: Use multiple backends simultaneously with priority fallback
|
|
11
|
+
- 📦 **Modular packages**: Install only what you need
|
|
12
|
+
- 🚀 **Built-in migration**: Easy data migration between drivers
|
|
13
|
+
- 🛡️ **Automatic fallback**: System continues working even if primary driver fails
|
|
14
|
+
- 🌍 **Cross-platform**: Works on Node.js, Bun, Deno (with appropriate drivers)
|
|
15
|
+
- 🔒 **Concurrency-safe**: Race condition protection for all concurrent operations
|
|
16
|
+
- ⏱️ **Timeout support**: Configurable timeouts to prevent hanging operations
|
|
17
|
+
|
|
18
|
+
## 📦 Packages
|
|
19
|
+
|
|
20
|
+
DeepBase v3.0 is split into modular packages:
|
|
21
|
+
|
|
22
|
+
- **`deepbase`** - Core library (includes `deepbase-json` as dependency)
|
|
23
|
+
- **`deepbase-json`** - JSON filesystem driver (no external DB dependencies!)
|
|
24
|
+
- **`deepbase-sqlite`** - SQLite driver (embedded database, ACID compliant)
|
|
25
|
+
- **`deepbase-mongodb`** - MongoDB driver
|
|
26
|
+
- **`deepbase-redis`** - Redis driver (vanilla, works with any Redis)
|
|
27
|
+
- **`deepbase-redis-json`** - Redis Stack driver (requires RedisJSON module)
|
|
28
|
+
|
|
29
|
+
## 🚀 Quick Start
|
|
30
|
+
|
|
31
|
+
### Simple JSON Driver
|
|
6
32
|
|
|
7
33
|
```bash
|
|
8
34
|
npm install deepbase
|
|
9
|
-
# deepbase
|
|
35
|
+
# deepbase automatically includes deepbase-json
|
|
10
36
|
```
|
|
11
37
|
|
|
12
|
-
|
|
38
|
+
```javascript
|
|
39
|
+
import DeepBase from 'deepbase';
|
|
13
40
|
|
|
14
|
-
|
|
41
|
+
// Option 1: Backward-compatible syntax (uses JSON driver by default)
|
|
42
|
+
const db = new DeepBase({ path: './data', name: 'mydb' });
|
|
43
|
+
await db.connect();
|
|
15
44
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- ✅ Version control friendly
|
|
45
|
+
// Option 2: Explicit JSON driver
|
|
46
|
+
import { JsonDriver } from 'deepbase';
|
|
47
|
+
const db = new DeepBase(new JsonDriver({ path: './data', name: 'mydb' }));
|
|
48
|
+
await db.connect();
|
|
21
49
|
|
|
22
|
-
|
|
50
|
+
await db.set('users', 'alice', { name: 'Alice', age: 30 });
|
|
51
|
+
const alice = await db.get('users', 'alice');
|
|
52
|
+
console.log(alice); // { name: 'Alice', age: 30 }
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Multi-Driver Setup (MongoDB + JSON Backup)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install deepbase deepbase-mongodb
|
|
59
|
+
```
|
|
23
60
|
|
|
24
61
|
```javascript
|
|
25
62
|
import DeepBase, { JsonDriver } from 'deepbase';
|
|
63
|
+
import MongoDriver from 'deepbase-mongodb';
|
|
26
64
|
|
|
27
|
-
const db = new DeepBase(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
65
|
+
const db = new DeepBase([
|
|
66
|
+
new MongoDriver({ url: 'mongodb://localhost:27017' }),
|
|
67
|
+
new JsonDriver({ path: './backup' })
|
|
68
|
+
], {
|
|
69
|
+
writeAll: true, // Write to all drivers
|
|
70
|
+
readFirst: true, // Read from first available
|
|
71
|
+
failOnPrimaryError: false // Continue if primary fails
|
|
72
|
+
});
|
|
31
73
|
|
|
32
74
|
await db.connect();
|
|
33
75
|
|
|
34
|
-
|
|
35
|
-
|
|
76
|
+
// Writes to both MongoDB and JSON
|
|
77
|
+
await db.set('config', 'version', '1.0.0');
|
|
78
|
+
|
|
79
|
+
// Reads from MongoDB (or JSON if MongoDB is down)
|
|
80
|
+
const version = await db.get('config', 'version');
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## 🔥 Core Features
|
|
84
|
+
|
|
85
|
+
### Set and Get Nested Data
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
await db.set('config', 'theme', 'dark');
|
|
89
|
+
await db.set('config', 'lang', 'en');
|
|
90
|
+
|
|
91
|
+
const theme = await db.get('config', 'theme'); // 'dark'
|
|
92
|
+
const config = await db.get('config'); // { theme: 'dark', lang: 'en' }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Add Items with Auto-Generated IDs
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const userPath = await db.add('users', { name: 'Bob', email: 'bob@example.com' });
|
|
99
|
+
// userPath: ['users', 'aB3xK9mL2n']
|
|
100
|
+
|
|
101
|
+
const user = await db.get(...userPath);
|
|
102
|
+
// { name: 'Bob', email: 'bob@example.com' }
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Increment and Decrement
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
await db.set('stats', 'views', 100);
|
|
109
|
+
await db.inc('stats', 'views', 50); // 150
|
|
110
|
+
await db.dec('stats', 'views', 30); // 120
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Update with Functions
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
await db.set('user', 'name', 'alice');
|
|
117
|
+
await db.upd('user', 'name', name => name.toUpperCase());
|
|
118
|
+
const name = await db.get('user', 'name'); // 'ALICE'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Keys, Values, Entries
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
await db.set('products', 'laptop', { price: 999 });
|
|
125
|
+
await db.set('products', 'mouse', { price: 29 });
|
|
126
|
+
|
|
127
|
+
const keys = await db.keys('products'); // ['laptop', 'mouse']
|
|
128
|
+
const values = await db.values('products'); // [{ price: 999 }, { price: 29 }]
|
|
129
|
+
const entries = await db.entries('products'); // [['laptop', {...}], ['mouse', {...}]]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 🔄 Migration Between Drivers
|
|
133
|
+
|
|
134
|
+
One of the most powerful features is built-in data migration:
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
import DeepBase from '@deepbase/core';
|
|
138
|
+
import JsonDriver from '@deepbase/json';
|
|
139
|
+
import MongoDriver from '@deepbase/mongodb';
|
|
140
|
+
|
|
141
|
+
// Setup with both drivers
|
|
142
|
+
const db = new DeepBase([
|
|
143
|
+
new JsonDriver({ path: './data', name: 'mydb' }), // Source (index 0)
|
|
144
|
+
new MongoDriver({ url: 'mongodb://localhost:27017' }) // Target (index 1)
|
|
145
|
+
]);
|
|
146
|
+
|
|
147
|
+
await db.connect();
|
|
148
|
+
|
|
149
|
+
// Migrate all data from JSON (0) to MongoDB (1)
|
|
150
|
+
const result = await db.migrate(0, 1, {
|
|
151
|
+
clear: true, // Clear target before migration
|
|
152
|
+
batchSize: 100, // Progress callback every 100 items
|
|
153
|
+
onProgress: (progress) => {
|
|
154
|
+
console.log(`Migrated ${progress.migrated} items`);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
console.log(`Migration complete: ${result.migrated} items, ${result.errors} errors`);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Sync All Drivers
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
// Copy data from primary (index 0) to all other drivers
|
|
165
|
+
await db.syncAll();
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## 🏗️ Advanced: Three-Tier Architecture
|
|
169
|
+
|
|
170
|
+
For maximum reliability, use multiple backends with priority:
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
import DeepBase from '@deepbase/core';
|
|
174
|
+
import MongoDriver from '@deepbase/mongodb';
|
|
175
|
+
import JsonDriver from '@deepbase/json';
|
|
176
|
+
import RedisDriver from '@deepbase/redis';
|
|
177
|
+
|
|
178
|
+
const db = new DeepBase([
|
|
179
|
+
new MongoDriver({ url: 'mongodb://localhost:27017' }), // Primary
|
|
180
|
+
new JsonDriver({ path: './persistence' }), // Backup
|
|
181
|
+
new RedisDriver({ url: 'redis://localhost:6379' }) // Cache
|
|
182
|
+
], {
|
|
183
|
+
writeAll: true, // Replicate writes to all three
|
|
184
|
+
readFirst: true, // Read from first available
|
|
185
|
+
failOnPrimaryError: false // Graceful degradation
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
await db.connect();
|
|
189
|
+
|
|
190
|
+
// Writes to all three backends
|
|
191
|
+
await db.set('users', 'john', { name: 'John' });
|
|
192
|
+
|
|
193
|
+
// If MongoDB fails, reads from JSON
|
|
194
|
+
// If both fail, reads from Redis
|
|
195
|
+
const user = await db.get('users', 'john');
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Benefits:**
|
|
199
|
+
- ✅ Automatic failover if any backend goes down
|
|
200
|
+
- ✅ Data replication across all backends
|
|
201
|
+
- ✅ Zero downtime during migrations
|
|
202
|
+
- ✅ Easy recovery from failures
|
|
203
|
+
|
|
204
|
+
## 📖 API Reference
|
|
205
|
+
|
|
206
|
+
### DeepBase Constructor
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
new DeepBase(drivers, options)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Parameters:**
|
|
213
|
+
- `drivers`: Single driver or array of drivers (in priority order)
|
|
214
|
+
- `options`:
|
|
215
|
+
- `writeAll` (default: `true`): Write to all drivers
|
|
216
|
+
- `readFirst` (default: `true`): Read from first available driver
|
|
217
|
+
- `failOnPrimaryError` (default: `true`): Throw if primary driver fails
|
|
218
|
+
- `lazyConnect` (default: `true`): Auto-connect on first operation
|
|
219
|
+
- `timeout` (default: `0`): Global timeout in ms (0 = disabled)
|
|
220
|
+
- `readTimeout` (default: `timeout`): Timeout for read operations in ms
|
|
221
|
+
- `writeTimeout` (default: `timeout`): Timeout for write operations in ms
|
|
222
|
+
- `connectTimeout` (default: `timeout`): Timeout for connection in ms
|
|
223
|
+
|
|
224
|
+
### Core Methods
|
|
225
|
+
|
|
226
|
+
- `await db.connect()` - Connect all drivers
|
|
227
|
+
- `await db.disconnect()` - Disconnect all drivers
|
|
228
|
+
- `await db.get(...path)` - Get value at path
|
|
229
|
+
- `await db.set(...path, value)` - Set value at path
|
|
230
|
+
- `await db.del(...path)` - Delete value at path
|
|
231
|
+
- `await db.inc(...path, amount)` - Increment numeric value
|
|
232
|
+
- `await db.dec(...path, amount)` - Decrement numeric value
|
|
233
|
+
- `await db.add(...path, value)` - Add item with auto-generated ID
|
|
234
|
+
- `await db.upd(...path, fn)` - Update value with function
|
|
235
|
+
- `await db.keys(...path)` - Get keys at path
|
|
236
|
+
- `await db.values(...path)` - Get values at path
|
|
237
|
+
- `await db.entries(...path)` - Get entries at path
|
|
238
|
+
|
|
239
|
+
### Migration Methods
|
|
240
|
+
|
|
241
|
+
- `await db.migrate(fromIndex, toIndex, options)` - Migrate data between drivers
|
|
242
|
+
- `await db.syncAll(options)` - Sync primary to all other drivers
|
|
243
|
+
- `db.getDriver(index)` - Get driver by index
|
|
244
|
+
- `db.getDrivers()` - Get all drivers
|
|
245
|
+
|
|
246
|
+
## 🔒 Concurrency Safety
|
|
247
|
+
|
|
248
|
+
DeepBase v3.0+ provides **built-in race condition protection** for all drivers:
|
|
249
|
+
|
|
250
|
+
### Protected Operations
|
|
251
|
+
- ✅ `inc()` / `dec()` - Atomic increment/decrement
|
|
252
|
+
- ✅ `upd()` - Atomic read-modify-write
|
|
253
|
+
- ✅ `set()` - Safe concurrent writes
|
|
254
|
+
- ✅ `add()` - Unique ID generation without collisions
|
|
255
|
+
|
|
256
|
+
### How it Works
|
|
257
|
+
|
|
258
|
+
**SQLite Driver**: Uses native SQLite transactions for atomic operations
|
|
259
|
+
```javascript
|
|
260
|
+
// 100 concurrent increments = exactly 100 (no race conditions)
|
|
261
|
+
await Promise.all(
|
|
262
|
+
Array.from({ length: 100 }, () => db.inc('counter', 1))
|
|
263
|
+
);
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**JSON Driver**: Uses operation queue to serialize writes
|
|
267
|
+
```javascript
|
|
268
|
+
// Concurrent updates are safe - no data loss
|
|
269
|
+
await Promise.all([
|
|
270
|
+
db.upd('account', acc => ({ ...acc, balance: acc.balance + 50 })),
|
|
271
|
+
db.upd('account', acc => ({ ...acc, lastAccess: Date.now() }))
|
|
272
|
+
]);
|
|
36
273
|
```
|
|
37
274
|
|
|
38
|
-
|
|
275
|
+
See [`examples/08-concurrency-safe.js`](./examples/08-concurrency-safe.js) for detailed examples.
|
|
276
|
+
|
|
277
|
+
## ⏱️ Timeout Configuration
|
|
278
|
+
|
|
279
|
+
Prevent operations from hanging indefinitely with configurable timeouts:
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
import DeepBase, { JsonDriver } from 'deepbase';
|
|
283
|
+
|
|
284
|
+
// Global timeout for all operations
|
|
285
|
+
const db = new DeepBase(new JsonDriver(), {
|
|
286
|
+
timeout: 5000 // 5 seconds for all operations
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Different timeouts for reads and writes
|
|
290
|
+
const db2 = new DeepBase([
|
|
291
|
+
new RedisDriver({ url: 'redis://slow-server:6379' }),
|
|
292
|
+
new JsonDriver({ path: './backup' }) // Fallback if Redis times out
|
|
293
|
+
], {
|
|
294
|
+
readTimeout: 2000, // 2 seconds for reads (get, keys, values, entries)
|
|
295
|
+
writeTimeout: 5000, // 5 seconds for writes (set, del, inc, dec, add, upd)
|
|
296
|
+
connectTimeout: 10000 // 10 seconds for connection
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
try {
|
|
300
|
+
const value = await db.get('some', 'key');
|
|
301
|
+
} catch (error) {
|
|
302
|
+
// Error: get() timed out after 2000ms
|
|
303
|
+
console.error(error.message);
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Timeout Options:**
|
|
308
|
+
- `timeout` (default: `0`): Global timeout in milliseconds for all operations (0 = disabled)
|
|
309
|
+
- `readTimeout` (default: `timeout`): Timeout for read operations
|
|
310
|
+
- `writeTimeout` (default: `timeout`): Timeout for write operations
|
|
311
|
+
- `connectTimeout` (default: `timeout`): Timeout for connection operation
|
|
312
|
+
|
|
313
|
+
**Use Cases:**
|
|
314
|
+
- 🛡️ **Network issues**: Prevent hanging on slow/unresponsive database servers
|
|
315
|
+
- 🔄 **Fast failover**: Combined with multi-driver setup for automatic fallback
|
|
316
|
+
- ⚡ **Performance SLAs**: Enforce response time requirements
|
|
317
|
+
- 🐛 **Debugging**: Identify slow operations during development
|
|
318
|
+
|
|
319
|
+
See [`examples/09-timeout.js`](./examples/09-timeout.js) for examples and [`TIMEOUT_FEATURE.md`](./TIMEOUT_FEATURE.md) for detailed documentation.
|
|
320
|
+
|
|
321
|
+
## 🎯 Available Drivers
|
|
322
|
+
|
|
323
|
+
### JSON Driver (`@deepbase/json`)
|
|
324
|
+
|
|
325
|
+
Filesystem-based JSON storage. Perfect for:
|
|
326
|
+
- Development and testing
|
|
327
|
+
- Small to medium datasets
|
|
328
|
+
- Human-readable data
|
|
329
|
+
- No external dependencies
|
|
39
330
|
|
|
40
331
|
```javascript
|
|
41
332
|
new JsonDriver({
|
|
42
|
-
path: './data',
|
|
43
|
-
name: '
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
stringify: JSON.stringify, // Custom JSON serializer
|
|
47
|
-
parse: JSON.parse // Custom JSON parser
|
|
333
|
+
path: './data', // Storage directory
|
|
334
|
+
name: 'mydb', // Filename (mydb.json)
|
|
335
|
+
stringify: JSON.stringify, // Custom serializer
|
|
336
|
+
parse: JSON.parse // Custom parser
|
|
48
337
|
})
|
|
49
338
|
```
|
|
50
339
|
|
|
51
|
-
|
|
340
|
+
### SQLite Driver (`@deepbase/sqlite`)
|
|
52
341
|
|
|
53
|
-
|
|
342
|
+
SQLite embedded database. Perfect for:
|
|
343
|
+
- Production applications
|
|
344
|
+
- Medium to large datasets
|
|
345
|
+
- Offline-first apps
|
|
346
|
+
- Desktop applications (Electron/Tauri)
|
|
347
|
+
- Serverless deployments
|
|
348
|
+
- ACID compliance required
|
|
54
349
|
|
|
55
|
-
|
|
350
|
+
```javascript
|
|
351
|
+
new SqliteDriver({
|
|
352
|
+
path: './data', // Storage directory
|
|
353
|
+
name: 'mydb' // Database filename (mydb.db)
|
|
354
|
+
})
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
No external dependencies required - embedded database!
|
|
358
|
+
|
|
359
|
+
### MongoDB Driver (`@deepbase/mongodb`)
|
|
360
|
+
|
|
361
|
+
MongoDB storage. Perfect for:
|
|
362
|
+
- Production applications
|
|
363
|
+
- Large datasets
|
|
364
|
+
- Complex queries
|
|
365
|
+
- Scalability
|
|
56
366
|
|
|
57
367
|
```javascript
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
//
|
|
368
|
+
new MongoDriver({
|
|
369
|
+
url: 'mongodb://localhost:27017',
|
|
370
|
+
database: 'myapp', // Database name
|
|
371
|
+
collection: 'documents' // Collection name
|
|
372
|
+
})
|
|
61
373
|
```
|
|
62
374
|
|
|
63
|
-
|
|
375
|
+
Requires MongoDB:
|
|
376
|
+
```bash
|
|
377
|
+
docker run -d -p 27017:27017 mongodb/mongodb-community-server:latest
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Redis Driver (`@deepbase/redis`)
|
|
381
|
+
|
|
382
|
+
Vanilla Redis storage (no modules required). Perfect for:
|
|
383
|
+
- Caching
|
|
384
|
+
- Session storage
|
|
385
|
+
- High-performance reads/writes
|
|
386
|
+
- Works with any Redis installation
|
|
387
|
+
|
|
388
|
+
```javascript
|
|
389
|
+
new RedisDriver({
|
|
390
|
+
url: 'redis://localhost:6379',
|
|
391
|
+
prefix: 'myapp' // Key prefix
|
|
392
|
+
})
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
Requires standard Redis:
|
|
396
|
+
```bash
|
|
397
|
+
docker run -d -p 6379:6379 redis:latest
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
**Note:** Uses JSON serialization. For atomic JSON operations, use `deepbase-redis-json` instead.
|
|
64
401
|
|
|
65
|
-
|
|
402
|
+
### Redis-JSON Driver (`@deepbase/redis-json`)
|
|
403
|
+
|
|
404
|
+
Redis Stack storage with RedisJSON module. Perfect for:
|
|
405
|
+
- Caching with large nested objects
|
|
406
|
+
- High-performance reads/writes
|
|
407
|
+
- Atomic JSON path operations
|
|
408
|
+
- Real-time applications
|
|
66
409
|
|
|
67
410
|
```javascript
|
|
68
|
-
import
|
|
411
|
+
import RedisDriver from 'deepbase-redis-json';
|
|
412
|
+
|
|
413
|
+
new RedisDriver({
|
|
414
|
+
url: 'redis://localhost:6379',
|
|
415
|
+
prefix: 'myapp' // Key prefix
|
|
416
|
+
})
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Requires Redis Stack (includes RedisJSON):
|
|
420
|
+
```bash
|
|
421
|
+
docker run -d -p 6379:6379 redis/redis-stack-server:latest
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
**Benefits over vanilla Redis driver:**
|
|
425
|
+
- Atomic JSON path operations
|
|
426
|
+
- More efficient for partial updates
|
|
427
|
+
- Native JSON.NUMINCRBY for atomic increments
|
|
428
|
+
|
|
429
|
+
## 🧪 Custom JSON Serialization
|
|
430
|
+
|
|
431
|
+
DeepBase supports custom JSON serialization in the JSON driver, allowing for circular references and complex data structures.
|
|
432
|
+
|
|
433
|
+
### Example with `flatted`:
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
import { parse, stringify } from 'flatted';
|
|
437
|
+
import DeepBase, { JsonDriver } from 'deepbase';
|
|
438
|
+
|
|
439
|
+
const db = new DeepBase(new JsonDriver({
|
|
440
|
+
path: './data',
|
|
441
|
+
name: 'mydb',
|
|
442
|
+
stringify,
|
|
443
|
+
parse
|
|
444
|
+
}));
|
|
445
|
+
|
|
446
|
+
await db.connect();
|
|
447
|
+
|
|
448
|
+
// Now you can store circular references
|
|
449
|
+
const obj = { name: 'circular' };
|
|
450
|
+
obj.self = obj; // circular reference
|
|
451
|
+
await db.set('circular', obj);
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Example with `CircularJSON`:
|
|
455
|
+
|
|
456
|
+
```javascript
|
|
457
|
+
const CircularJSON = require('circular-json');
|
|
458
|
+
import DeepBase, { JsonDriver } from 'deepbase';
|
|
69
459
|
|
|
70
460
|
const db = new DeepBase(new JsonDriver({
|
|
461
|
+
path: './data',
|
|
462
|
+
name: 'mydb',
|
|
71
463
|
stringify: (obj) => CircularJSON.stringify(obj, null, 4),
|
|
72
464
|
parse: CircularJSON.parse
|
|
73
465
|
}));
|
|
466
|
+
|
|
467
|
+
await db.connect();
|
|
468
|
+
|
|
469
|
+
await db.set("a", "b", { circular: {} });
|
|
470
|
+
await db.set("a", "b", "circular", "self", await db.get("a", "b"));
|
|
74
471
|
```
|
|
75
472
|
|
|
76
|
-
|
|
473
|
+
## 🔒 Secure Storage with Encryption
|
|
474
|
+
|
|
475
|
+
You can create encrypted storage by extending DeepBase with custom serialization:
|
|
476
|
+
|
|
477
|
+
```javascript
|
|
478
|
+
import CryptoJS from 'crypto-js';
|
|
479
|
+
import DeepBase, { JsonDriver } from 'deepbase';
|
|
480
|
+
|
|
481
|
+
class DeepbaseSecure extends DeepBase {
|
|
482
|
+
constructor(opts) {
|
|
483
|
+
const encryptionKey = opts.encryptionKey;
|
|
484
|
+
delete opts.encryptionKey;
|
|
485
|
+
|
|
486
|
+
// Create JSON driver with encryption
|
|
487
|
+
const driver = new JsonDriver({
|
|
488
|
+
...opts,
|
|
489
|
+
stringify: (obj) => {
|
|
490
|
+
const iv = CryptoJS.lib.WordArray.random(128 / 8);
|
|
491
|
+
const encrypted = CryptoJS.AES.encrypt(
|
|
492
|
+
JSON.stringify(obj),
|
|
493
|
+
encryptionKey,
|
|
494
|
+
{ iv }
|
|
495
|
+
);
|
|
496
|
+
return iv.toString(CryptoJS.enc.Hex) + ':' + encrypted.toString();
|
|
497
|
+
},
|
|
498
|
+
parse: (encryptedData) => {
|
|
499
|
+
const [ivHex, encrypted] = encryptedData.split(':');
|
|
500
|
+
const iv = CryptoJS.enc.Hex.parse(ivHex);
|
|
501
|
+
const bytes = CryptoJS.AES.decrypt(encrypted, encryptionKey, { iv });
|
|
502
|
+
return JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
super(driver);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
77
509
|
|
|
78
|
-
|
|
510
|
+
// Create an encrypted database
|
|
511
|
+
const secureDB = new DeepbaseSecure({
|
|
512
|
+
path: './data',
|
|
513
|
+
name: 'secure_db',
|
|
514
|
+
encryptionKey: 'your-secret-key-here'
|
|
515
|
+
});
|
|
79
516
|
|
|
80
|
-
|
|
517
|
+
await secureDB.connect();
|
|
81
518
|
|
|
82
|
-
|
|
519
|
+
// Use it like a regular DeepBase instance
|
|
520
|
+
await secureDB.set("users", "admin", { password: "secret123" });
|
|
521
|
+
const admin = await secureDB.get("users", "admin");
|
|
522
|
+
console.log(admin); // { password: 'secret123' }
|
|
83
523
|
|
|
84
|
-
|
|
85
|
-
data/
|
|
86
|
-
mydb.json
|
|
87
|
-
users.json
|
|
88
|
-
config.json
|
|
524
|
+
// But the file on disk is encrypted!
|
|
89
525
|
```
|
|
90
526
|
|
|
91
|
-
##
|
|
527
|
+
## 🛠️ Creating Custom Drivers
|
|
92
528
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
529
|
+
Extend `DeepBaseDriver` to create your own drivers:
|
|
530
|
+
|
|
531
|
+
```javascript
|
|
532
|
+
import { DeepBaseDriver } from '@deepbase/core';
|
|
533
|
+
|
|
534
|
+
class MyCustomDriver extends DeepBaseDriver {
|
|
535
|
+
async connect() { /* ... */ }
|
|
536
|
+
async disconnect() { /* ... */ }
|
|
537
|
+
async get(...args) { /* ... */ }
|
|
538
|
+
async set(...args) { /* ... */ }
|
|
539
|
+
async del(...args) { /* ... */ }
|
|
540
|
+
async inc(...args) { /* ... */ }
|
|
541
|
+
async dec(...args) { /* ... */ }
|
|
542
|
+
async add(...args) { /* ... */ }
|
|
543
|
+
async upd(...args) { /* ... */ }
|
|
109
544
|
}
|
|
110
545
|
```
|
|
111
546
|
|
|
112
|
-
##
|
|
547
|
+
## 📚 Examples
|
|
113
548
|
|
|
114
|
-
|
|
115
|
-
- **Testing**: Easy to inspect and modify test data
|
|
116
|
-
- **Small Apps**: Perfect for configuration and small datasets
|
|
117
|
-
- **Backup**: Use as secondary driver for data backup
|
|
118
|
-
- **Version Control**: Human-readable, git-friendly format
|
|
549
|
+
Check the `/examples` folder for complete examples:
|
|
119
550
|
|
|
120
|
-
|
|
551
|
+
1. **Simple JSON** - Basic single-driver usage
|
|
552
|
+
2. **Multi-Driver** - MongoDB with JSON backup
|
|
553
|
+
3. **Migration** - Moving data from JSON to MongoDB
|
|
554
|
+
4. **Three-Tier** - Full production-ready setup
|
|
121
555
|
|
|
122
|
-
|
|
556
|
+
## 🤔 Why DeepBase?
|
|
123
557
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
558
|
+
- ⚡ **Simple API**: Intuitive nested object operations
|
|
559
|
+
- 🔌 **Flexible**: Use any storage backend
|
|
560
|
+
- 🛡️ **Resilient**: Automatic failover and recovery
|
|
561
|
+
- 📦 **Modular**: Install only what you need
|
|
562
|
+
- 🚀 **Fast**: Optimized for performance
|
|
563
|
+
- 🌍 **Universal**: Works across platforms
|
|
564
|
+
- 💪 **Production-ready**: Battle-tested patterns
|
|
127
565
|
|
|
128
|
-
|
|
129
|
-
new JsonDriver({ path: './data' }),
|
|
130
|
-
new MongoDriver({ url: 'mongodb://localhost:27017' })
|
|
131
|
-
]);
|
|
566
|
+
## 🤝 Contributing
|
|
132
567
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
568
|
+
Contributions are welcome! Whether it's:
|
|
569
|
+
- 🐛 Bug reports
|
|
570
|
+
- 💡 Feature requests
|
|
571
|
+
- 📖 Documentation improvements
|
|
572
|
+
- 🔌 New drivers
|
|
573
|
+
|
|
574
|
+
## 📄 License
|
|
575
|
+
|
|
576
|
+
MIT License - Copyright (c) Martin Clasen
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
🚀 **Try DeepBase today and simplify your data persistence!**
|
|
581
|
+
|
|
582
|
+
## 📊 Performance
|
|
583
|
+
|
|
584
|
+
DeepBase v3.0 delivers exceptional performance:
|
|
585
|
+
|
|
586
|
+
- ⚡ **Redis**: 6,000-7,700 ops/sec for most operations
|
|
587
|
+
- 📁 **JSON**: 600,000+ ops/sec for cached reads
|
|
588
|
+
- 🍃 **MongoDB**: 1,600-2,900 ops/sec balanced performance
|
|
136
589
|
|
|
137
|
-
|
|
590
|
+
See [Benchmark Results](./BENCHMARK_RESULTS.md) for detailed performance analysis.
|
|
138
591
|
|
|
139
|
-
|
|
592
|
+
For more information, visit [GitHub](https://github.com/clasen/DeepBase)
|
|
140
593
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepbase-json",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "⚡ DeepBase JSON - filesystem driver",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.cjs",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"steno": "^0.4.4"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"deepbase": "^3.
|
|
18
|
+
"deepbase": "^3.2.0"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
21
|
"test": "mocha test/test.js"
|