nodejs-json-db 0.0.1
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/LICENSE +21 -0
- package/README.md +348 -0
- package/dist/index.d.ts +1052 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/package.json +88 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Rashed Iqbal
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# nodejs-json-db
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/nodejs-json-db)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
A production-ready, lightweight JSON-based database for Node.js and Electron applications. Zero external database dependencies, fully typed, with a MongoDB-like query API and optional high-concurrency mode.
|
|
8
|
+
|
|
9
|
+
## โจ Features
|
|
10
|
+
|
|
11
|
+
- ๐ **Zero Dependencies** - No external database server required
|
|
12
|
+
- ๐ฆ **Dual Module Support** - Works with both ESM and CommonJS
|
|
13
|
+
- ๐ **Type-Safe** - Full TypeScript support with generics
|
|
14
|
+
- ๐ **MongoDB-like Queries** - Familiar query operators (`$eq`, `$gt`, `$in`, `$regex`, etc.)
|
|
15
|
+
- โก **High Performance** - Memory caching with atomic file writes
|
|
16
|
+
- ๐ **High-Concurrency Mode** - Partitioned storage with write batching for massive throughput
|
|
17
|
+
- โ
**Schema Validation** - Optional Zod integration for document validation
|
|
18
|
+
- ๐ฅ๏ธ **Electron Ready** - Perfect for desktop applications
|
|
19
|
+
- ๐งช **Well Tested** - 107 tests with comprehensive coverage
|
|
20
|
+
|
|
21
|
+
## ๐ฆ Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install nodejs-json-db
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
yarn add nodejs-json-db
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For schema validation (optional):
|
|
32
|
+
```bash
|
|
33
|
+
npm install zod
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## ๐ Quick Start
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { JsonDB, Document } from 'nodejs-json-db';
|
|
40
|
+
|
|
41
|
+
interface User extends Document {
|
|
42
|
+
_id: string;
|
|
43
|
+
name: string;
|
|
44
|
+
email: string;
|
|
45
|
+
age: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const db = new JsonDB({ dataDir: './data' });
|
|
49
|
+
await db.connect();
|
|
50
|
+
|
|
51
|
+
const users = db.collection<User>('users');
|
|
52
|
+
|
|
53
|
+
// Insert
|
|
54
|
+
const user = await users.insert({
|
|
55
|
+
name: 'John Doe',
|
|
56
|
+
email: 'john@example.com',
|
|
57
|
+
age: 30,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Find
|
|
61
|
+
const found = await users.findOne({ email: 'john@example.com' });
|
|
62
|
+
|
|
63
|
+
// Update
|
|
64
|
+
await users.updateById(user._id, { $set: { age: 31 } });
|
|
65
|
+
|
|
66
|
+
// Delete
|
|
67
|
+
await users.deleteById(user._id);
|
|
68
|
+
|
|
69
|
+
await db.close();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## ๐ Benchmarks
|
|
73
|
+
|
|
74
|
+
Performance tested with documents up to 1 million records:
|
|
75
|
+
|
|
76
|
+
### Write Performance (insertMany)
|
|
77
|
+
|
|
78
|
+
| Documents | Standard Mode | High-Concurrency Mode |
|
|
79
|
+
|-----------|---------------|----------------------|
|
|
80
|
+
| 100,000 | 390K docs/sec (56 MB/s) | 355K docs/sec (51 MB/s) |
|
|
81
|
+
| 500,000 | 382K docs/sec (55 MB/s) | **423K docs/sec (61 MB/s)** โ
|
|
|
82
|
+
| 1,000,000 | 392K docs/sec (56 MB/s) | **392K docs/sec (56 MB/s)** |
|
|
83
|
+
|
|
84
|
+
### Read Performance (find)
|
|
85
|
+
|
|
86
|
+
| Documents | Standard Mode | High-Concurrency Mode |
|
|
87
|
+
|-----------|---------------|----------------------|
|
|
88
|
+
| 1,000 | 648K docs/sec (93 MB/s) | **803K docs/sec (115 MB/s)** โ
|
|
|
89
|
+
| 10,000 | 1.5M docs/sec (218 MB/s) | **2.2M docs/sec (309 MB/s)** โ
|
|
|
90
|
+
| 100,000+ | **2.8M+ docs/sec** | 2.0M docs/sec |
|
|
91
|
+
|
|
92
|
+
Run benchmarks yourself:
|
|
93
|
+
```bash
|
|
94
|
+
npx tsx examples/benchmark.ts
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## ๐ High-Concurrency Mode
|
|
98
|
+
|
|
99
|
+
For applications handling thousands of concurrent requests, enable high-concurrency mode:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
const db = new JsonDB({
|
|
103
|
+
dataDir: './data',
|
|
104
|
+
highConcurrency: {
|
|
105
|
+
enabled: true,
|
|
106
|
+
partitions: 16, // Data shards (default: 16)
|
|
107
|
+
batchSize: 1000, // Writes before auto-flush (default: 1000)
|
|
108
|
+
flushInterval: 100, // Max ms before flush (default: 100)
|
|
109
|
+
maxConcurrentIO: 4, // Parallel I/O operations (default: 4)
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
await db.connect();
|
|
114
|
+
const users = db.collection('users');
|
|
115
|
+
|
|
116
|
+
// Fast parallel inserts (skips duplicate check)
|
|
117
|
+
await Promise.all(
|
|
118
|
+
Array.from({ length: 10000 }, (_, i) =>
|
|
119
|
+
users.insertFast({ name: `User ${i}`, email: `user${i}@test.com` })
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// Always flush before shutdown
|
|
124
|
+
await db.flush();
|
|
125
|
+
await db.close();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### When to Use High-Concurrency Mode
|
|
129
|
+
|
|
130
|
+
| Use Case | Recommended Mode |
|
|
131
|
+
|----------|-----------------|
|
|
132
|
+
| Desktop apps, small datasets | Standard |
|
|
133
|
+
| Web servers with concurrent requests | High-Concurrency |
|
|
134
|
+
| Bulk data import | Either (both fast) |
|
|
135
|
+
| Real-time applications | High-Concurrency |
|
|
136
|
+
|
|
137
|
+
## โ
Schema Validation (Zod)
|
|
138
|
+
|
|
139
|
+
Validate documents before insertion using Zod schemas:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { z } from 'zod';
|
|
143
|
+
import { JsonDB, ValidationError } from 'nodejs-json-db';
|
|
144
|
+
|
|
145
|
+
const UserSchema = z.object({
|
|
146
|
+
_id: z.string(),
|
|
147
|
+
name: z.string().min(1),
|
|
148
|
+
email: z.string().email(),
|
|
149
|
+
age: z.number().int().positive().optional(),
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
type User = z.infer<typeof UserSchema>;
|
|
153
|
+
|
|
154
|
+
const db = new JsonDB({ dataDir: './data' });
|
|
155
|
+
await db.connect();
|
|
156
|
+
|
|
157
|
+
// Pass schema when creating collection
|
|
158
|
+
const users = db.collection<User>('users', { schema: UserSchema });
|
|
159
|
+
|
|
160
|
+
// โ
Valid - inserts successfully
|
|
161
|
+
await users.insert({ name: 'John', email: 'john@example.com' });
|
|
162
|
+
|
|
163
|
+
// โ Invalid - throws ValidationError
|
|
164
|
+
try {
|
|
165
|
+
await users.insert({ name: '', email: 'not-an-email' });
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (error instanceof ValidationError) {
|
|
168
|
+
console.log(error.issues); // [{path: ['name'], message: '...'}, ...]
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## ๐ API Reference
|
|
174
|
+
|
|
175
|
+
### JsonDB Options
|
|
176
|
+
|
|
177
|
+
| Option | Type | Default | Description |
|
|
178
|
+
|--------|------|---------|-------------|
|
|
179
|
+
| `dataDir` | `string` | **required** | Path to store JSON files |
|
|
180
|
+
| `autoSave` | `boolean` | `true` | Auto-save after writes |
|
|
181
|
+
| `saveDebounce` | `number` | `0` | Debounce time (ms) for saves |
|
|
182
|
+
| `prettyPrint` | `boolean` | `true` | Format JSON files |
|
|
183
|
+
| `fileExtension` | `string` | `.json` | Custom file extension |
|
|
184
|
+
| `highConcurrency` | `object` | `undefined` | Enable high-concurrency mode |
|
|
185
|
+
|
|
186
|
+
### JsonDB Methods
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
await db.connect(); // Initialize database
|
|
190
|
+
await db.close(); // Close connection
|
|
191
|
+
db.collection<T>('name', {schema?}); // Get typed collection
|
|
192
|
+
await db.listCollections(); // List all collections
|
|
193
|
+
await db.hasCollection('name'); // Check if exists
|
|
194
|
+
await db.dropCollection('name'); // Delete collection
|
|
195
|
+
await db.drop(); // Delete all collections
|
|
196
|
+
await db.flush(); // Flush pending writes
|
|
197
|
+
db.isHighConcurrencyMode(); // Check mode
|
|
198
|
+
db.getStats(); // Get HC stats (if enabled)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Collection Methods
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// Insert
|
|
205
|
+
await collection.insert(doc); // With duplicate check
|
|
206
|
+
await collection.insertFast(doc); // Skip duplicate check (faster)
|
|
207
|
+
await collection.insertMany(docs); // Bulk insert
|
|
208
|
+
|
|
209
|
+
// Find
|
|
210
|
+
await collection.find(query?, options?); // Find matching docs
|
|
211
|
+
await collection.findOne(query); // Find first match
|
|
212
|
+
await collection.findById(id); // Find by ID
|
|
213
|
+
await collection.count(query?); // Count matches
|
|
214
|
+
await collection.getAll(); // Get all documents
|
|
215
|
+
|
|
216
|
+
// Update
|
|
217
|
+
await collection.update(query, update); // Update many
|
|
218
|
+
await collection.updateOne(query, update); // Update first match
|
|
219
|
+
await collection.updateById(id, update); // Update by ID
|
|
220
|
+
|
|
221
|
+
// Delete
|
|
222
|
+
await collection.delete(query); // Delete many
|
|
223
|
+
await collection.deleteOne(query); // Delete first match
|
|
224
|
+
await collection.deleteById(id); // Delete by ID
|
|
225
|
+
await collection.clear(); // Clear all documents
|
|
226
|
+
await collection.drop(); // Drop collection
|
|
227
|
+
|
|
228
|
+
// Utility
|
|
229
|
+
await collection.flush(); // Force save pending writes
|
|
230
|
+
collection.getName(); // Get collection name
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## ๐ Query Operators
|
|
234
|
+
|
|
235
|
+
### Comparison
|
|
236
|
+
|
|
237
|
+
| Operator | Example |
|
|
238
|
+
|----------|---------|
|
|
239
|
+
| `$eq` | `{ age: { $eq: 25 } }` |
|
|
240
|
+
| `$ne` | `{ status: { $ne: 'deleted' } }` |
|
|
241
|
+
| `$gt` / `$gte` | `{ age: { $gte: 18 } }` |
|
|
242
|
+
| `$lt` / `$lte` | `{ price: { $lt: 100 } }` |
|
|
243
|
+
| `$in` / `$nin` | `{ role: { $in: ['admin', 'mod'] } }` |
|
|
244
|
+
|
|
245
|
+
### String
|
|
246
|
+
|
|
247
|
+
| Operator | Example |
|
|
248
|
+
|----------|---------|
|
|
249
|
+
| `$regex` | `{ email: { $regex: /@gmail\.com$/ } }` |
|
|
250
|
+
| `$startsWith` | `{ name: { $startsWith: 'John' } }` |
|
|
251
|
+
| `$endsWith` | `{ email: { $endsWith: '.com' } }` |
|
|
252
|
+
|
|
253
|
+
### Logical
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
// AND (implicit)
|
|
257
|
+
{ active: true, age: { $gte: 18 } }
|
|
258
|
+
|
|
259
|
+
// OR
|
|
260
|
+
{ $or: [{ role: 'admin' }, { role: 'mod' }] }
|
|
261
|
+
|
|
262
|
+
// NOT
|
|
263
|
+
{ $not: { status: 'deleted' } }
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Existence
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
{ email: { $exists: true } } // Field exists
|
|
270
|
+
{ deletedAt: { $exists: false } } // Field doesn't exist
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## ๐ Update Operators
|
|
274
|
+
|
|
275
|
+
| Operator | Description | Example |
|
|
276
|
+
|----------|-------------|---------|
|
|
277
|
+
| `$set` | Set field | `{ $set: { name: 'New' } }` |
|
|
278
|
+
| `$unset` | Remove field | `{ $unset: { temp: true } }` |
|
|
279
|
+
| `$inc` | Increment | `{ $inc: { views: 1 } }` |
|
|
280
|
+
| `$push` | Add to array | `{ $push: { tags: 'new' } }` |
|
|
281
|
+
| `$pull` | Remove from array | `{ $pull: { tags: 'old' } }` |
|
|
282
|
+
| `$addToSet` | Add unique | `{ $addToSet: { tags: 'unique' } }` |
|
|
283
|
+
|
|
284
|
+
## ๐ฅ๏ธ Electron Integration
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
import { app } from 'electron';
|
|
288
|
+
import { JsonDB } from 'nodejs-json-db';
|
|
289
|
+
import path from 'path';
|
|
290
|
+
|
|
291
|
+
const db = new JsonDB({
|
|
292
|
+
dataDir: path.join(app.getPath('userData'), 'database'),
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
await db.connect();
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## ๐ Data Storage
|
|
299
|
+
|
|
300
|
+
Standard mode stores one JSON file per collection:
|
|
301
|
+
```
|
|
302
|
+
data/
|
|
303
|
+
โโโ users.json
|
|
304
|
+
โโโ posts.json
|
|
305
|
+
โโโ settings.json
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
High-concurrency mode partitions data:
|
|
309
|
+
```
|
|
310
|
+
data/
|
|
311
|
+
โโโ users_p0.json
|
|
312
|
+
โโโ users_p1.json
|
|
313
|
+
โโโ users_p2.json
|
|
314
|
+
โโโ ...
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## ๐งช Examples
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# Basic usage
|
|
321
|
+
npx tsx examples/basic-usage.ts
|
|
322
|
+
|
|
323
|
+
# Schema validation
|
|
324
|
+
npx tsx examples/schema-example.ts
|
|
325
|
+
|
|
326
|
+
# Benchmark
|
|
327
|
+
npx tsx examples/benchmark.ts
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## ๐ง Development
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
# Install dependencies
|
|
334
|
+
yarn install
|
|
335
|
+
|
|
336
|
+
# Run tests
|
|
337
|
+
yarn test
|
|
338
|
+
|
|
339
|
+
# Build
|
|
340
|
+
yarn build
|
|
341
|
+
|
|
342
|
+
# Lint
|
|
343
|
+
yarn lint
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## ๐ License
|
|
347
|
+
|
|
348
|
+
MIT ยฉ [Rashed Iqbal](https://github.com/iqbal-rashed)
|