jexidb 2.0.0 → 2.0.2
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 +527 -556
- package/dist/FileHandler.js +1 -1
- package/dist/JSONLDatabase.js +65 -3
- package/dist/index.js +23 -4
- package/package.json +1 -1
- package/src/FileHandler.js +1 -1
- package/src/JSONLDatabase.js +62 -3
- package/src/index.js +17 -3
package/dist/FileHandler.js
CHANGED
|
@@ -606,7 +606,7 @@ class FileHandler {
|
|
|
606
606
|
} catch (error) {
|
|
607
607
|
if (error.code === 'ENOENT') {
|
|
608
608
|
return {
|
|
609
|
-
version: '2.0.
|
|
609
|
+
version: '2.0.1',
|
|
610
610
|
// Keep version number for internal tracking
|
|
611
611
|
created: new Date().toISOString(),
|
|
612
612
|
lastModified: new Date().toISOString(),
|
package/dist/JSONLDatabase.js
CHANGED
|
@@ -36,8 +36,17 @@ class JSONLDatabase extends _events.EventEmitter {
|
|
|
36
36
|
this.options = {
|
|
37
37
|
batchSize: 100,
|
|
38
38
|
// Batch size for inserts
|
|
39
|
+
create: true,
|
|
40
|
+
// Create database if it doesn't exist (default: true)
|
|
41
|
+
clear: false,
|
|
42
|
+
// Clear database on load if not empty (default: false)
|
|
39
43
|
...options
|
|
40
44
|
};
|
|
45
|
+
|
|
46
|
+
// If clear is true, create should also be true
|
|
47
|
+
if (this.options.clear === true) {
|
|
48
|
+
this.options.create = true;
|
|
49
|
+
}
|
|
41
50
|
this.isInitialized = false;
|
|
42
51
|
this.offsets = [];
|
|
43
52
|
this.indexOffset = 0;
|
|
@@ -80,10 +89,49 @@ class JSONLDatabase extends _events.EventEmitter {
|
|
|
80
89
|
await _fs.promises.mkdir(dir, {
|
|
81
90
|
recursive: true
|
|
82
91
|
});
|
|
92
|
+
|
|
93
|
+
// Check if file exists before loading
|
|
94
|
+
const fileExists = await _fs.promises.access(this.filePath).then(() => true).catch(() => false);
|
|
95
|
+
|
|
96
|
+
// Handle clear option
|
|
97
|
+
if (this.options.clear && fileExists) {
|
|
98
|
+
await _fs.promises.writeFile(this.filePath, '');
|
|
99
|
+
this.offsets = [];
|
|
100
|
+
this.indexOffset = 0;
|
|
101
|
+
this.recordCount = 0;
|
|
102
|
+
console.log(`Database cleared: ${this.filePath}`);
|
|
103
|
+
this.isInitialized = true;
|
|
104
|
+
this.emit('init');
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Handle create option
|
|
109
|
+
if (!fileExists) {
|
|
110
|
+
if (this.options.create) {
|
|
111
|
+
await _fs.promises.writeFile(this.filePath, '');
|
|
112
|
+
this.offsets = [];
|
|
113
|
+
this.indexOffset = 0;
|
|
114
|
+
this.recordCount = 0;
|
|
115
|
+
console.log(`Database created: ${this.filePath}`);
|
|
116
|
+
this.isInitialized = true;
|
|
117
|
+
this.emit('init');
|
|
118
|
+
return;
|
|
119
|
+
} else {
|
|
120
|
+
throw new Error(`Database file does not exist: ${this.filePath}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Load existing database
|
|
83
125
|
await this.loadDataWithOffsets();
|
|
84
126
|
this.isInitialized = true;
|
|
85
127
|
this.emit('init');
|
|
86
128
|
} catch (error) {
|
|
129
|
+
// If create is false and file doesn't exist or is corrupted, throw error
|
|
130
|
+
if (!this.options.create) {
|
|
131
|
+
throw new Error(`Failed to load database: ${error.message}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// If create is true, initialize empty database
|
|
87
135
|
this.recordCount = 0;
|
|
88
136
|
this.offsets = [];
|
|
89
137
|
this.indexOffset = 0;
|
|
@@ -171,9 +219,7 @@ class JSONLDatabase extends _events.EventEmitter {
|
|
|
171
219
|
}
|
|
172
220
|
this.recordCount = this.offsets.length;
|
|
173
221
|
} catch (error) {
|
|
174
|
-
|
|
175
|
-
this.offsets = [];
|
|
176
|
-
this.indexOffset = 0;
|
|
222
|
+
throw error; // Re-throw to be handled by init()
|
|
177
223
|
}
|
|
178
224
|
}
|
|
179
225
|
async loadLegacyFormat(lines) {
|
|
@@ -821,6 +867,22 @@ class JSONLDatabase extends _events.EventEmitter {
|
|
|
821
867
|
};
|
|
822
868
|
}
|
|
823
869
|
|
|
870
|
+
/**
|
|
871
|
+
* Compatibility method: readColumnIndex - gets unique values from indexed columns only
|
|
872
|
+
* Maintains compatibility with JexiDB v1 code
|
|
873
|
+
* @param {string} column - The column name to get unique values from
|
|
874
|
+
* @returns {Set} Set of unique values in the column (indexed columns only)
|
|
875
|
+
*/
|
|
876
|
+
readColumnIndex(column) {
|
|
877
|
+
// Only works with indexed columns
|
|
878
|
+
if (this.indexes[column]) {
|
|
879
|
+
return new Set(this.indexes[column].keys());
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// For non-indexed columns, throw error
|
|
883
|
+
throw new Error(`Column '${column}' is not indexed. Only indexed columns are supported.`);
|
|
884
|
+
}
|
|
885
|
+
|
|
824
886
|
// Intelligent criteria matching for non-indexed fields
|
|
825
887
|
matchesCriteria(record, criteria, options = {}) {
|
|
826
888
|
const {
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.Database = void 0;
|
|
6
7
|
Object.defineProperty(exports, "FileHandler", {
|
|
7
8
|
enumerable: true,
|
|
8
9
|
get: function () {
|
|
@@ -207,11 +208,15 @@ class JexiDBCompatibility extends _JSONLDatabase.default {
|
|
|
207
208
|
}
|
|
208
209
|
|
|
209
210
|
/**
|
|
210
|
-
*
|
|
211
|
+
* Streaming iterator over records without loading all into memory
|
|
212
|
+
* Supports a limited subset of options: { limit }
|
|
211
213
|
*/
|
|
212
214
|
async *walk(options = {}) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
+
// Delegate to core engine streaming implementation
|
|
216
|
+
// Ensure pending inserts are flushed by calling super.walk
|
|
217
|
+
for await (const record of super.walk({
|
|
218
|
+
limit: options.limit
|
|
219
|
+
})) {
|
|
215
220
|
yield record;
|
|
216
221
|
}
|
|
217
222
|
}
|
|
@@ -251,6 +256,16 @@ class JexiDBCompatibility extends _JSONLDatabase.default {
|
|
|
251
256
|
}
|
|
252
257
|
return result;
|
|
253
258
|
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Compatibility method: readColumnIndex - gets unique values from indexed columns only
|
|
262
|
+
* Maintains compatibility with JexiDB v1 code
|
|
263
|
+
* @param {string} column - The column name to get unique values from
|
|
264
|
+
* @returns {Set} Set of unique values in the column (indexed columns only)
|
|
265
|
+
*/
|
|
266
|
+
readColumnIndex(column) {
|
|
267
|
+
return super.readColumnIndex(column);
|
|
268
|
+
}
|
|
254
269
|
}
|
|
255
270
|
|
|
256
271
|
/**
|
|
@@ -279,7 +294,11 @@ class JexiDBCompatibility extends _JSONLDatabase.default {
|
|
|
279
294
|
*/
|
|
280
295
|
|
|
281
296
|
// Export the compatibility wrapper as default
|
|
282
|
-
var _default = exports.default = JexiDBCompatibility; //
|
|
297
|
+
var _default = exports.default = JexiDBCompatibility; // Retrocompat: named export 'Database' (JexiDB v1 used { Database })
|
|
298
|
+
const Database = exports.Database = JexiDBCompatibility;
|
|
299
|
+
|
|
300
|
+
// Export auxiliary classes for advanced use
|
|
301
|
+
|
|
283
302
|
// Export useful constants
|
|
284
303
|
const OPERATORS = exports.OPERATORS = {
|
|
285
304
|
GT: '>',
|
package/package.json
CHANGED
package/src/FileHandler.js
CHANGED
|
@@ -600,7 +600,7 @@ class FileHandler {
|
|
|
600
600
|
} catch (error) {
|
|
601
601
|
if (error.code === 'ENOENT') {
|
|
602
602
|
return {
|
|
603
|
-
version: '2.0.
|
|
603
|
+
version: '2.0.1', // Keep version number for internal tracking
|
|
604
604
|
created: new Date().toISOString(),
|
|
605
605
|
lastModified: new Date().toISOString(),
|
|
606
606
|
recordCount: 0,
|
package/src/JSONLDatabase.js
CHANGED
|
@@ -30,9 +30,16 @@ class JSONLDatabase extends EventEmitter {
|
|
|
30
30
|
|
|
31
31
|
this.options = {
|
|
32
32
|
batchSize: 100, // Batch size for inserts
|
|
33
|
+
create: true, // Create database if it doesn't exist (default: true)
|
|
34
|
+
clear: false, // Clear database on load if not empty (default: false)
|
|
33
35
|
...options
|
|
34
36
|
};
|
|
35
37
|
|
|
38
|
+
// If clear is true, create should also be true
|
|
39
|
+
if (this.options.clear === true) {
|
|
40
|
+
this.options.create = true;
|
|
41
|
+
}
|
|
42
|
+
|
|
36
43
|
this.isInitialized = false;
|
|
37
44
|
this.offsets = [];
|
|
38
45
|
this.indexOffset = 0;
|
|
@@ -77,12 +84,50 @@ class JSONLDatabase extends EventEmitter {
|
|
|
77
84
|
const dir = path.dirname(this.filePath);
|
|
78
85
|
await fs.mkdir(dir, { recursive: true });
|
|
79
86
|
|
|
87
|
+
// Check if file exists before loading
|
|
88
|
+
const fileExists = await fs.access(this.filePath).then(() => true).catch(() => false);
|
|
89
|
+
|
|
90
|
+
// Handle clear option
|
|
91
|
+
if (this.options.clear && fileExists) {
|
|
92
|
+
await fs.writeFile(this.filePath, '');
|
|
93
|
+
this.offsets = [];
|
|
94
|
+
this.indexOffset = 0;
|
|
95
|
+
this.recordCount = 0;
|
|
96
|
+
console.log(`Database cleared: ${this.filePath}`);
|
|
97
|
+
this.isInitialized = true;
|
|
98
|
+
this.emit('init');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Handle create option
|
|
103
|
+
if (!fileExists) {
|
|
104
|
+
if (this.options.create) {
|
|
105
|
+
await fs.writeFile(this.filePath, '');
|
|
106
|
+
this.offsets = [];
|
|
107
|
+
this.indexOffset = 0;
|
|
108
|
+
this.recordCount = 0;
|
|
109
|
+
console.log(`Database created: ${this.filePath}`);
|
|
110
|
+
this.isInitialized = true;
|
|
111
|
+
this.emit('init');
|
|
112
|
+
return;
|
|
113
|
+
} else {
|
|
114
|
+
throw new Error(`Database file does not exist: ${this.filePath}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Load existing database
|
|
80
119
|
await this.loadDataWithOffsets();
|
|
81
120
|
|
|
82
121
|
this.isInitialized = true;
|
|
83
122
|
this.emit('init');
|
|
84
123
|
|
|
85
124
|
} catch (error) {
|
|
125
|
+
// If create is false and file doesn't exist or is corrupted, throw error
|
|
126
|
+
if (!this.options.create) {
|
|
127
|
+
throw new Error(`Failed to load database: ${error.message}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// If create is true, initialize empty database
|
|
86
131
|
this.recordCount = 0;
|
|
87
132
|
this.offsets = [];
|
|
88
133
|
this.indexOffset = 0;
|
|
@@ -180,9 +225,7 @@ class JSONLDatabase extends EventEmitter {
|
|
|
180
225
|
this.recordCount = this.offsets.length;
|
|
181
226
|
|
|
182
227
|
} catch (error) {
|
|
183
|
-
|
|
184
|
-
this.offsets = [];
|
|
185
|
-
this.indexOffset = 0;
|
|
228
|
+
throw error; // Re-throw to be handled by init()
|
|
186
229
|
}
|
|
187
230
|
}
|
|
188
231
|
|
|
@@ -867,6 +910,22 @@ class JSONLDatabase extends EventEmitter {
|
|
|
867
910
|
};
|
|
868
911
|
}
|
|
869
912
|
|
|
913
|
+
/**
|
|
914
|
+
* Compatibility method: readColumnIndex - gets unique values from indexed columns only
|
|
915
|
+
* Maintains compatibility with JexiDB v1 code
|
|
916
|
+
* @param {string} column - The column name to get unique values from
|
|
917
|
+
* @returns {Set} Set of unique values in the column (indexed columns only)
|
|
918
|
+
*/
|
|
919
|
+
readColumnIndex(column) {
|
|
920
|
+
// Only works with indexed columns
|
|
921
|
+
if (this.indexes[column]) {
|
|
922
|
+
return new Set(this.indexes[column].keys());
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
// For non-indexed columns, throw error
|
|
926
|
+
throw new Error(`Column '${column}' is not indexed. Only indexed columns are supported.`);
|
|
927
|
+
}
|
|
928
|
+
|
|
870
929
|
// Intelligent criteria matching for non-indexed fields
|
|
871
930
|
matchesCriteria(record, criteria, options = {}) {
|
|
872
931
|
const { caseInsensitive = false } = options;
|
package/src/index.js
CHANGED
|
@@ -183,11 +183,13 @@ class JexiDBCompatibility extends JSONLDatabase {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
/**
|
|
186
|
-
*
|
|
186
|
+
* Streaming iterator over records without loading all into memory
|
|
187
|
+
* Supports a limited subset of options: { limit }
|
|
187
188
|
*/
|
|
188
189
|
async *walk(options = {}) {
|
|
189
|
-
|
|
190
|
-
|
|
190
|
+
// Delegate to core engine streaming implementation
|
|
191
|
+
// Ensure pending inserts are flushed by calling super.walk
|
|
192
|
+
for await (const record of super.walk({ limit: options.limit })) {
|
|
191
193
|
yield record;
|
|
192
194
|
}
|
|
193
195
|
}
|
|
@@ -227,6 +229,16 @@ class JexiDBCompatibility extends JSONLDatabase {
|
|
|
227
229
|
}
|
|
228
230
|
return result;
|
|
229
231
|
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Compatibility method: readColumnIndex - gets unique values from indexed columns only
|
|
235
|
+
* Maintains compatibility with JexiDB v1 code
|
|
236
|
+
* @param {string} column - The column name to get unique values from
|
|
237
|
+
* @returns {Set} Set of unique values in the column (indexed columns only)
|
|
238
|
+
*/
|
|
239
|
+
readColumnIndex(column) {
|
|
240
|
+
return super.readColumnIndex(column);
|
|
241
|
+
}
|
|
230
242
|
}
|
|
231
243
|
|
|
232
244
|
/**
|
|
@@ -256,6 +268,8 @@ class JexiDBCompatibility extends JSONLDatabase {
|
|
|
256
268
|
|
|
257
269
|
// Export the compatibility wrapper as default
|
|
258
270
|
export default JexiDBCompatibility;
|
|
271
|
+
// Retrocompat: named export 'Database' (JexiDB v1 used { Database })
|
|
272
|
+
export const Database = JexiDBCompatibility;
|
|
259
273
|
|
|
260
274
|
// Export auxiliary classes for advanced use
|
|
261
275
|
export { FileHandler, IndexManager, IntegrityChecker };
|