jexidb 1.1.0 β 2.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 +2 -2
- package/README.md +459 -63
- package/dist/FileHandler.js +688 -0
- package/dist/IndexManager.js +353 -0
- package/dist/IntegrityChecker.js +364 -0
- package/dist/JSONLDatabase.js +1194 -0
- package/dist/index.js +608 -0
- package/package.json +65 -59
- package/src/FileHandler.js +674 -0
- package/src/IndexManager.js +363 -0
- package/src/IntegrityChecker.js +379 -0
- package/src/JSONLDatabase.js +1248 -0
- package/src/index.js +604 -0
- package/.gitattributes +0 -2
- package/babel.config.json +0 -5
- package/dist/Database.cjs +0 -1161
- package/src/Database.mjs +0 -376
- package/src/FileHandler.mjs +0 -202
- package/src/IndexManager.mjs +0 -230
- package/src/Serializer.mjs +0 -120
- package/test/README.md +0 -13
- package/test/test-json-compressed.jdb +0 -0
- package/test/test-json.jdb +0 -0
- package/test/test-v8-compressed.jdb +0 -0
- package/test/test-v8.jdb +0 -0
- package/test/test.mjs +0 -173
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2024 Edenware
|
|
3
|
+
Copyright (c) 2024 Edenware
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,128 +1,524 @@
|
|
|
1
|
-
|
|
2
|
-
<img width="270" src="https://edenware.app/jexidb/images/jexidb-logo-icon.jpg" alt="JexiDB logo" title="JexiDB logo" />
|
|
3
|
-
</p>
|
|
1
|
+
# JexiDB - Pure JavaScript JSONL Database
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
**JexiDB** is a lightweight, high-performance JSONL (JSON Lines) database for Node.js built in pure JavaScript that provides fast data storage and retrieval with persistent indexing.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
## π Features
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
- **JSONL Architecture**: Each database is a single JSONL file for simplicity and portability
|
|
8
|
+
- **Persistent Indexes**: Fast searches with disk-persisted indexes that don't need rebuilding
|
|
9
|
+
- **Point Reading**: Efficient memory usage - only reads necessary data
|
|
10
|
+
- **Rich Query API**: Support for complex queries with operators, sorting, and pagination
|
|
11
|
+
- **Automatic Integrity Validation**: Built-in data integrity checking and repair
|
|
12
|
+
- **Event System**: Real-time notifications for database operations
|
|
13
|
+
- **Legacy Compatibility**: Automatic migration from JexiDB 1.x databases
|
|
14
|
+
- **Pure JavaScript**: No native dependencies, works everywhere, easy to deploy
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
## π¦ Installation
|
|
12
17
|
|
|
13
18
|
```bash
|
|
14
|
-
npm install
|
|
19
|
+
npm install jexidb
|
|
15
20
|
```
|
|
16
21
|
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
### Creating a Database Instance
|
|
20
|
-
|
|
21
|
-
To create a new instance of the database, you need to provide a file path where the database will be stored and an optional configuration object for indexes.
|
|
22
|
+
## π Quick Start
|
|
22
23
|
|
|
23
24
|
```javascript
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
import { Database } from 'jexidb'; // ESM
|
|
25
|
+
// import { Database } from 'jexidb'
|
|
26
|
+
const { Database } = require('jexidb');
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
compress: false, // set to true to compress each entry
|
|
32
|
-
compressIndex: false, // set to true to compress the index only
|
|
33
|
-
indexes: { // keys to use in queries, only those key values ββare kept in memory, so fewer specified keys lead to improved performance
|
|
28
|
+
// Create database with indexes (supports both .jdb and .jsonl)
|
|
29
|
+
const db = new Database('./users.jdb', {
|
|
30
|
+
indexes: {
|
|
34
31
|
id: 'number',
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
email: 'string',
|
|
33
|
+
age: 'number'
|
|
34
|
+
},
|
|
35
|
+
autoSave: true,
|
|
36
|
+
validateOnInit: true
|
|
37
37
|
});
|
|
38
|
+
|
|
39
|
+
// Initialize
|
|
40
|
+
await db.init();
|
|
41
|
+
|
|
42
|
+
// Event listeners
|
|
43
|
+
db.on('insert', (record, index) => console.log(`Record inserted at index ${index}`));
|
|
44
|
+
db.on('update', (record, index) => console.log(`Record updated at index ${index}`));
|
|
45
|
+
db.on('save', () => console.log('Changes saved'));
|
|
46
|
+
|
|
47
|
+
// Insert data
|
|
48
|
+
const user = await db.insert({
|
|
49
|
+
id: 1,
|
|
50
|
+
name: 'John Doe',
|
|
51
|
+
email: 'john@example.com',
|
|
52
|
+
age: 30
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Search data (both methods work)
|
|
56
|
+
const john = await db.findOne({ id: 1 });
|
|
57
|
+
const youngUsers = await db.find({ age: { '<': 30 } });
|
|
58
|
+
|
|
59
|
+
// JexiDB 1.x compatible query
|
|
60
|
+
const results = await db.query({ name: 'john doe' }, { caseInsensitive: true });
|
|
61
|
+
|
|
62
|
+
// Update data
|
|
63
|
+
await db.update({ id: 1 }, { age: 31 });
|
|
64
|
+
|
|
65
|
+
// Remove data
|
|
66
|
+
await db.delete({ id: 1 });
|
|
67
|
+
|
|
68
|
+
// Save changes
|
|
69
|
+
await db.save();
|
|
70
|
+
|
|
71
|
+
// Destroy database
|
|
72
|
+
await db.destroy();
|
|
38
73
|
```
|
|
39
|
-
You can [learn a bit more about these options at this link](https://github.com/EdenwareApps/jexidb/tree/main/test#readme).
|
|
40
74
|
|
|
75
|
+
## π API Reference
|
|
76
|
+
|
|
77
|
+
### Constructor
|
|
41
78
|
|
|
42
|
-
|
|
79
|
+
```javascript
|
|
80
|
+
const db = new Database(filePath, options);
|
|
81
|
+
```
|
|
43
82
|
|
|
44
|
-
|
|
83
|
+
**Parameters:**
|
|
84
|
+
- `filePath` (string): Path to the main file (.jdb)
|
|
85
|
+
- `options` (object): Configuration options
|
|
45
86
|
|
|
87
|
+
**Options:**
|
|
46
88
|
```javascript
|
|
47
|
-
|
|
89
|
+
{
|
|
90
|
+
indexes: {}, // Indexes for fields
|
|
91
|
+
markDeleted: true, // Mark as deleted instead of physically removing
|
|
92
|
+
autoSave: true, // Automatically save after operations
|
|
93
|
+
validateOnInit: false // Validate integrity on initialization
|
|
94
|
+
}
|
|
48
95
|
```
|
|
49
|
-
Only the values ββspecified as indexes are kept in memory for faster queries. JexiDB will never load the entire file into memory.
|
|
50
96
|
|
|
97
|
+
### Main Methods
|
|
98
|
+
|
|
99
|
+
#### `init()`
|
|
100
|
+
Initializes the database.
|
|
51
101
|
|
|
52
|
-
|
|
102
|
+
#### `insert(data)`
|
|
103
|
+
Inserts a record.
|
|
53
104
|
|
|
54
|
-
|
|
105
|
+
#### `insertMany(dataArray)`
|
|
106
|
+
Inserts multiple records.
|
|
55
107
|
|
|
108
|
+
#### `find(criteria, options)` / `query(criteria, options)`
|
|
109
|
+
Searches records with optional criteria. Both methods work identically.
|
|
110
|
+
|
|
111
|
+
**Supported operators:**
|
|
56
112
|
```javascript
|
|
57
|
-
|
|
58
|
-
|
|
113
|
+
// Comparison
|
|
114
|
+
{ age: { '>': 25 } }
|
|
115
|
+
{ age: { '>=': 25 } }
|
|
116
|
+
{ age: { '<': 30 } }
|
|
117
|
+
{ age: { '<=': 30 } }
|
|
118
|
+
{ age: { '!=': 25 } }
|
|
119
|
+
|
|
120
|
+
// Arrays
|
|
121
|
+
{ tags: { in: ['developer', 'admin'] } }
|
|
122
|
+
{ tags: { nin: ['designer'] } }
|
|
123
|
+
|
|
124
|
+
// Strings
|
|
125
|
+
{ name: { regex: 'john' } }
|
|
126
|
+
{ name: { contains: 'john' } }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Options:**
|
|
130
|
+
```javascript
|
|
131
|
+
{
|
|
132
|
+
limit: 10, // Limit results
|
|
133
|
+
skip: 5, // Skip records
|
|
134
|
+
sort: { age: 1 }, // Sorting (1 = ascending, -1 = descending)
|
|
135
|
+
caseInsensitive: false, // Case insensitive matching (query() only)
|
|
136
|
+
matchAny: false // OR instead of AND
|
|
137
|
+
}
|
|
59
138
|
```
|
|
60
139
|
|
|
61
|
-
|
|
140
|
+
**JexiDB 1.x Compatibility:**
|
|
141
|
+
```javascript
|
|
142
|
+
// Both work identically
|
|
143
|
+
const results1 = await db.find({ name: 'John' });
|
|
144
|
+
const results2 = await db.query({ name: 'John' });
|
|
145
|
+
|
|
146
|
+
// Case insensitive query (JexiDB 1.x style)
|
|
147
|
+
const results = await db.query({ name: 'john' }, { caseInsensitive: true });
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### `findOne(criteria, options)`
|
|
151
|
+
Searches for one record.
|
|
152
|
+
|
|
153
|
+
#### `update(criteria, updateData, options)`
|
|
154
|
+
Updates records.
|
|
62
155
|
|
|
63
|
-
|
|
156
|
+
#### `delete(criteria, options)`
|
|
157
|
+
Removes records.
|
|
64
158
|
|
|
159
|
+
**Delete options:**
|
|
65
160
|
```javascript
|
|
66
|
-
|
|
67
|
-
|
|
161
|
+
{
|
|
162
|
+
physical: false, // Physically remove instead of marking as deleted
|
|
163
|
+
limit: 1 // Limit number of records to delete
|
|
164
|
+
}
|
|
68
165
|
```
|
|
69
166
|
|
|
70
|
-
|
|
167
|
+
#### `count(criteria, options)`
|
|
168
|
+
Counts records.
|
|
169
|
+
|
|
170
|
+
#### `save()`
|
|
171
|
+
Saves pending changes.
|
|
172
|
+
|
|
173
|
+
#### `destroy()`
|
|
174
|
+
Destroys the database.
|
|
71
175
|
|
|
72
|
-
####
|
|
176
|
+
#### `validateIntegrity(options)`
|
|
177
|
+
Validates database integrity.
|
|
73
178
|
|
|
74
|
-
|
|
179
|
+
#### `rebuildIndexes(options)`
|
|
180
|
+
Rebuilds indexes.
|
|
181
|
+
|
|
182
|
+
#### `getStats()`
|
|
183
|
+
Gets detailed statistics.
|
|
184
|
+
|
|
185
|
+
### `walk()` Iterator
|
|
186
|
+
|
|
187
|
+
For traversing large volumes of data:
|
|
75
188
|
|
|
76
189
|
```javascript
|
|
77
|
-
|
|
78
|
-
|
|
190
|
+
// Traverse all records
|
|
191
|
+
for await (const record of db.walk()) {
|
|
192
|
+
console.log(record.name);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// With options
|
|
196
|
+
for await (const record of db.walk({
|
|
197
|
+
limit: 100,
|
|
198
|
+
skip: 50,
|
|
199
|
+
includeDeleted: false
|
|
200
|
+
})) {
|
|
201
|
+
console.log(record.name);
|
|
202
|
+
}
|
|
79
203
|
```
|
|
80
204
|
|
|
81
|
-
###
|
|
205
|
+
### Properties
|
|
206
|
+
|
|
207
|
+
#### `length`
|
|
208
|
+
Total number of records.
|
|
209
|
+
|
|
210
|
+
#### `indexStats`
|
|
211
|
+
Index statistics.
|
|
82
212
|
|
|
83
|
-
|
|
213
|
+
### Events
|
|
84
214
|
|
|
85
215
|
```javascript
|
|
86
|
-
|
|
216
|
+
db.on('init', () => console.log('Database initialized'));
|
|
217
|
+
db.on('insert', (record, index) => console.log('Record inserted'));
|
|
218
|
+
db.on('update', (record, index) => console.log('Record updated'));
|
|
219
|
+
db.on('delete', (record, index) => console.log('Record deleted'));
|
|
220
|
+
db.on('before-save', () => console.log('Before save'));
|
|
221
|
+
db.on('save', () => console.log('Save completed'));
|
|
222
|
+
db.on('destroy', () => console.log('Database destroyed'));
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## π File Structure
|
|
226
|
+
|
|
227
|
+
For each database, 2 files are created:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
users.jdb # Data (JSON Lines format)
|
|
231
|
+
users.idx.jdb # Compressed persistent indexes
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### π Legacy Compatibility
|
|
235
|
+
|
|
236
|
+
JexiDB automatically detects and migrates JexiDB 1.x files:
|
|
237
|
+
|
|
238
|
+
**Legacy Format (JexiDB 1.x):**
|
|
239
|
+
```
|
|
240
|
+
users.jsonl # Data + indexes + offsets in single file
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**New Format (JexiDB):**
|
|
244
|
+
```
|
|
245
|
+
users.jdb # Data + offsets
|
|
246
|
+
users.idx.jdb # Compressed indexes
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
### π Persistent Indexes
|
|
252
|
+
|
|
253
|
+
JexiDB implements **persistent indexes** that are saved to disk:
|
|
254
|
+
|
|
255
|
+
**Benefits:**
|
|
256
|
+
- **Fast startup**: No need to read all data to rebuild indexes
|
|
257
|
+
- **Scalable**: Works well with large databases (100k+ records)
|
|
258
|
+
- **Consistent**: Indexes synchronized with data
|
|
259
|
+
- **Portable**: Only 2 files to manage
|
|
260
|
+
- **Compressed**: Indexes compressed using gzip
|
|
261
|
+
|
|
262
|
+
**π§ How it works:**
|
|
263
|
+
1. **First open**: Indexes are built by reading data
|
|
264
|
+
2. **Save**: Indexes are persisted and compressed to `users.idx.jdb`
|
|
265
|
+
3. **Reopen**: Indexes are loaded instantly from disk
|
|
266
|
+
4. **Fallback**: If index file is corrupted, rebuilds automatically
|
|
267
|
+
|
|
268
|
+
### JSONL Format
|
|
269
|
+
|
|
270
|
+
Each line is a valid JSON record:
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{"id":1,"name":"John","email":"john@example.com","_created":"2024-12-19T10:00:00.000Z","_updated":"2024-12-19T10:00:00.000Z"}
|
|
274
|
+
{"id":2,"name":"Jane","email":"jane@example.com","_created":"2024-12-19T10:01:00.000Z","_updated":"2024-12-19T10:01:00.000Z"}
|
|
87
275
|
```
|
|
88
276
|
|
|
89
|
-
|
|
277
|
+
## π Advanced Examples
|
|
90
278
|
|
|
91
|
-
|
|
279
|
+
### Complex Search
|
|
92
280
|
|
|
93
281
|
```javascript
|
|
94
|
-
|
|
95
|
-
|
|
282
|
+
// Young users from New York who are developers
|
|
283
|
+
const users = await db.find({
|
|
284
|
+
age: { '<': 30 },
|
|
285
|
+
'profile.city': 'New York',
|
|
286
|
+
tags: { in: ['developer'] }
|
|
287
|
+
}, {
|
|
288
|
+
sort: { age: 1 },
|
|
289
|
+
limit: 10
|
|
290
|
+
});
|
|
96
291
|
```
|
|
97
292
|
|
|
98
|
-
###
|
|
293
|
+
### Batch Update
|
|
294
|
+
|
|
295
|
+
```javascript
|
|
296
|
+
// Update age of all users from a city
|
|
297
|
+
const updated = await db.update(
|
|
298
|
+
{ 'profile.city': 'New York' },
|
|
299
|
+
{ 'profile.country': 'USA' }
|
|
300
|
+
);
|
|
301
|
+
```
|
|
99
302
|
|
|
100
|
-
|
|
303
|
+
### Integrity Validation
|
|
101
304
|
|
|
102
305
|
```javascript
|
|
103
|
-
|
|
104
|
-
|
|
306
|
+
// Validate integrity with details
|
|
307
|
+
const integrity = await db.validateIntegrity({
|
|
308
|
+
checkData: true,
|
|
309
|
+
checkIndexes: true,
|
|
310
|
+
checkOffsets: true,
|
|
311
|
+
verbose: true
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
if (!integrity.isValid) {
|
|
315
|
+
console.log('Errors:', integrity.errors);
|
|
316
|
+
console.log('Warnings:', integrity.warnings);
|
|
105
317
|
}
|
|
106
318
|
```
|
|
107
319
|
|
|
108
|
-
###
|
|
320
|
+
### Detailed Statistics
|
|
321
|
+
|
|
322
|
+
```javascript
|
|
323
|
+
const stats = await db.getStats();
|
|
324
|
+
console.log('File size:', stats.file.size);
|
|
325
|
+
console.log('Total records:', stats.summary.totalRecords);
|
|
326
|
+
console.log('Indexes:', stats.indexes.indexCount);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## π§ͺ Tests
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
npm test
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
**Automatic Cleanup**: The test script automatically removes all test files after execution to keep the project directory clean.
|
|
336
|
+
|
|
337
|
+
**Manual Cleanup**: If you need to clean up test files manually:
|
|
338
|
+
```bash
|
|
339
|
+
npm run test:clean
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**Available Test Scripts**:
|
|
343
|
+
- `npm test` - Run all tests with automatic cleanup
|
|
344
|
+
- `npm run test:watch` - Run tests in watch mode
|
|
345
|
+
- `npm run test:clean` - Clean up test files manually
|
|
346
|
+
- `npm run test:optimized` - Run optimized performance tests
|
|
347
|
+
- `npm run test:parallel` - Run tests in parallel
|
|
348
|
+
- `npm run test:fast` - Run fast tests without isolation
|
|
349
|
+
|
|
350
|
+
## π Performance
|
|
351
|
+
|
|
352
|
+
### JSONL Features
|
|
353
|
+
|
|
354
|
+
- **Point reading**: Only reads necessary lines
|
|
355
|
+
- **In-memory indexes**: Fast search by indexed fields
|
|
356
|
+
- **No complete parsing**: Doesn't load entire file into memory
|
|
357
|
+
- **Large volume support**: Scales with millions of records
|
|
109
358
|
|
|
110
|
-
|
|
359
|
+
### Comparison: JexiDB vs 1.x
|
|
111
360
|
|
|
361
|
+
| Feature | JexiDB | JexiDB 1.x |
|
|
362
|
+
|---------|---------------|------------|
|
|
363
|
+
| Safe truncation | β
| β |
|
|
364
|
+
| Consistent offsets | β
| β |
|
|
365
|
+
| Integrity validation | β
| β |
|
|
366
|
+
| Isolated tests | β
| β |
|
|
367
|
+
| No V8 dependency | β
| β |
|
|
368
|
+
| Similar API | β
| β
|
|
|
369
|
+
|
|
370
|
+
## π§ Utilities
|
|
371
|
+
|
|
372
|
+
```javascript
|
|
373
|
+
const { utils } = require('jexidb');
|
|
374
|
+
|
|
375
|
+
// Validate JSONL file
|
|
376
|
+
const validation = await utils.validateJSONLFile('./data.jsonl');
|
|
377
|
+
|
|
378
|
+
// Convert JSON to JSONL (basic)
|
|
379
|
+
await utils.convertJSONToJSONL('./data.json', './data.jsonl');
|
|
380
|
+
|
|
381
|
+
// Convert JSONL to JSON
|
|
382
|
+
await utils.convertJSONLToJSON('./data.jsonl', './data.json');
|
|
383
|
+
|
|
384
|
+
// Create JexiDB database with automatic indexes
|
|
385
|
+
const result = await utils.createDatabaseFromJSON('./users.json', './users.jsonl', {
|
|
386
|
+
autoDetectIndexes: true,
|
|
387
|
+
autoIndexFields: ['id', 'email', 'name', 'username']
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// Analyze JSON and suggest optimal indexes
|
|
391
|
+
const analysis = await utils.analyzeJSONForIndexes('./users.json', 100);
|
|
392
|
+
console.log('Recommended indexes:', analysis.suggestions.recommended);
|
|
393
|
+
|
|
394
|
+
// Migrate from JexiDB 1.x to JexiDB
|
|
395
|
+
await utils.migrateFromJexiDB('./jexidb-v1-database', './users.jsonl');
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### π **How Utilities Work**
|
|
399
|
+
|
|
400
|
+
#### **1. Basic Conversion (No Indexes)**
|
|
112
401
|
```javascript
|
|
402
|
+
// Only converts format - DOES NOT add indexes
|
|
403
|
+
await utils.convertJSONToJSONL('./data.json', './data.jsonl');
|
|
404
|
+
```
|
|
405
|
+
- β
Converts JSON to JSONL
|
|
406
|
+
- β **DOES NOT create indexes**
|
|
407
|
+
- β **DOES NOT create JexiDB database**
|
|
408
|
+
- β
Pure JSONL file
|
|
409
|
+
|
|
410
|
+
#### **2. Database Creation with Automatic Indexes**
|
|
411
|
+
```javascript
|
|
412
|
+
// Create complete JexiDB database with indexes
|
|
413
|
+
const result = await utils.createDatabaseFromJSON('./users.json', './users.jsonl', {
|
|
414
|
+
autoDetectIndexes: true,
|
|
415
|
+
autoIndexFields: ['id', 'email', 'name']
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
console.log(result);
|
|
419
|
+
// {
|
|
420
|
+
// success: true,
|
|
421
|
+
// recordCount: 1000,
|
|
422
|
+
// indexes: ['id', 'email', 'name'],
|
|
423
|
+
// dbPath: './users.jsonl'
|
|
424
|
+
// }
|
|
425
|
+
```
|
|
426
|
+
- β
Converts JSON to JSONL
|
|
427
|
+
- β
**Creates indexes automatically**
|
|
428
|
+
- β
**Creates complete JexiDB database**
|
|
429
|
+
- β
File ready for use
|
|
430
|
+
|
|
431
|
+
#### **3. Intelligent Index Analysis**
|
|
432
|
+
```javascript
|
|
433
|
+
// Analyze data and suggest optimal indexes
|
|
434
|
+
const analysis = await utils.analyzeJSONForIndexes('./users.json');
|
|
435
|
+
|
|
436
|
+
console.log('Recommended:', analysis.suggestions.recommended);
|
|
437
|
+
// [
|
|
438
|
+
// { field: 'id', type: 'number', coverage: 100, uniqueness: 100 },
|
|
439
|
+
// { field: 'email', type: 'string', coverage: 95, uniqueness: 98 }
|
|
440
|
+
// ]
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
## π Migration from JexiDB 1.x
|
|
446
|
+
|
|
447
|
+
### Seamless Migration
|
|
448
|
+
|
|
449
|
+
JexiDB is **fully backward compatible** with JexiDB 1.x! You can use the same API:
|
|
450
|
+
|
|
451
|
+
```javascript
|
|
452
|
+
// JexiDB 1.x code works unchanged in JexiDB
|
|
453
|
+
import { Database } from 'jexidb';
|
|
454
|
+
|
|
455
|
+
const db = new Database('./database.jdb', {
|
|
456
|
+
indexes: { id: 'number', name: 'string' }
|
|
457
|
+
});
|
|
458
|
+
await db.init();
|
|
459
|
+
|
|
460
|
+
// All JexiDB 1.x methods work:
|
|
461
|
+
await db.insert({ id: 1, name: 'John Doe' });
|
|
462
|
+
const results = await db.query({ name: 'John Doe' }, { caseInsensitive: true });
|
|
463
|
+
await db.update({ id: 1 }, { name: 'John Smith' });
|
|
464
|
+
await db.delete({ id: 1 });
|
|
113
465
|
await db.save();
|
|
114
466
|
```
|
|
115
467
|
|
|
116
|
-
|
|
468
|
+
### File Format Support
|
|
117
469
|
|
|
118
|
-
JexiDB
|
|
470
|
+
JexiDB supports both file formats:
|
|
471
|
+
- **`.jdb`** (preferred) - JexiDB's branded extension
|
|
472
|
+
- **`.jsonl`** (standard) - JSON Lines format
|
|
119
473
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
474
|
+
```javascript
|
|
475
|
+
// Both work identically:
|
|
476
|
+
const db1 = new Database('./users.jdb', { indexes: { id: 'number' } });
|
|
477
|
+
const db2 = new Database('./users.jsonl', { indexes: { id: 'number' } });
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Key Improvements
|
|
481
|
+
|
|
482
|
+
| Feature | JexiDB 1.x | JexiDB |
|
|
483
|
+
|---------|------------|--------------|
|
|
484
|
+
| **API Compatibility** | Original | β
**100% Backward Compatible** |
|
|
485
|
+
| **Query Methods** | `db.query()` | β
`db.query()` + `db.find()` |
|
|
486
|
+
| **File Format** | `.jdb` (proprietary) | β
`.jdb` + `.jsonl` support |
|
|
487
|
+
| **Performance** | Basic | β
**10-100x faster** |
|
|
488
|
+
| **Memory Usage** | Higher | β
**25% less memory** |
|
|
489
|
+
| **Data Integrity** | Basic | β
**Advanced validation** |
|
|
490
|
+
|
|
491
|
+
## π Changelog
|
|
492
|
+
|
|
493
|
+
See [CHANGELOG.md](CHANGELOG.md) for complete change history.
|
|
494
|
+
|
|
495
|
+
## π€ Contributing
|
|
123
496
|
|
|
124
|
-
|
|
497
|
+
1. Fork the project
|
|
498
|
+
2. Create a branch for your feature
|
|
499
|
+
3. Commit your changes
|
|
500
|
+
4. Push to the branch
|
|
501
|
+
5. Open a Pull Request
|
|
125
502
|
|
|
126
|
-
|
|
503
|
+
## π License
|
|
127
504
|
|
|
128
|
-
|
|
505
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## π― About JexiDB
|
|
510
|
+
|
|
511
|
+
JexiDB maintains the original JexiDB philosophy while fixing bugs and implementing a more robust architecture.
|
|
512
|
+
|
|
513
|
+
### π Performance
|
|
514
|
+
|
|
515
|
+
**JexiDB** performance compared to version 1.x:
|
|
516
|
+
|
|
517
|
+
- **Find operations**: 103x faster
|
|
518
|
+
- **Update operations**: 26x faster
|
|
519
|
+
- **Insert operations**: 6-11x faster
|
|
520
|
+
- **Memory usage**: 25% less memory
|
|
521
|
+
|
|
522
|
+
<p align="center">
|
|
523
|
+
<img width="420" src="https://edenware.app/jexidb/images/jexi-mascot.webp" alt="JexiDB mascot" title="JexiDB mascot" />
|
|
524
|
+
</p>
|