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.
@@ -606,7 +606,7 @@ class FileHandler {
606
606
  } catch (error) {
607
607
  if (error.code === 'ENOENT') {
608
608
  return {
609
- version: '2.0.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(),
@@ -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
- this.recordCount = 0;
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
- * Compatibility method: walk() -> find() with async iteration
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
- const results = await this.find({}, options);
214
- for (const record of results) {
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; // Export auxiliary classes for advanced use
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jexidb",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "JexiDB - A fast and reliable local CRUD database for Electron apps with pure JavaScript JSONL architecture",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./src/index.js",
@@ -600,7 +600,7 @@ class FileHandler {
600
600
  } catch (error) {
601
601
  if (error.code === 'ENOENT') {
602
602
  return {
603
- version: '2.0.0', // Keep version number for internal tracking
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,
@@ -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
- this.recordCount = 0;
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
- * Compatibility method: walk() -> find() with async iteration
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
- const results = await this.find({}, options);
190
- for (const record of results) {
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 };