jexidb 2.1.1 → 2.1.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.
Files changed (47) hide show
  1. package/dist/Database.cjs +7621 -113
  2. package/package.json +9 -2
  3. package/src/Database.mjs +244 -79
  4. package/src/SchemaManager.mjs +325 -268
  5. package/src/Serializer.mjs +20 -1
  6. package/src/managers/QueryManager.mjs +74 -18
  7. package/.babelrc +0 -13
  8. package/.gitattributes +0 -2
  9. package/CHANGELOG.md +0 -140
  10. package/babel.config.json +0 -5
  11. package/docs/API.md +0 -1057
  12. package/docs/EXAMPLES.md +0 -701
  13. package/docs/README.md +0 -194
  14. package/examples/iterate-usage-example.js +0 -157
  15. package/examples/simple-iterate-example.js +0 -115
  16. package/jest.config.js +0 -24
  17. package/scripts/README.md +0 -47
  18. package/scripts/benchmark-array-serialization.js +0 -108
  19. package/scripts/clean-test-files.js +0 -75
  20. package/scripts/prepare.js +0 -31
  21. package/scripts/run-tests.js +0 -80
  22. package/scripts/score-mode-demo.js +0 -45
  23. package/test/$not-operator-with-and.test.js +0 -282
  24. package/test/README.md +0 -8
  25. package/test/close-init-cycle.test.js +0 -256
  26. package/test/coverage-method.test.js +0 -93
  27. package/test/critical-bugs-fixes.test.js +0 -1069
  28. package/test/deserialize-corruption-fixes.test.js +0 -296
  29. package/test/exists-method.test.js +0 -318
  30. package/test/explicit-indexes-comparison.test.js +0 -219
  31. package/test/filehandler-non-adjacent-ranges-bug.test.js +0 -175
  32. package/test/index-line-number-regression.test.js +0 -100
  33. package/test/index-missing-index-data.test.js +0 -91
  34. package/test/index-persistence.test.js +0 -491
  35. package/test/index-serialization.test.js +0 -314
  36. package/test/indexed-query-mode.test.js +0 -360
  37. package/test/insert-session-auto-flush.test.js +0 -353
  38. package/test/iterate-method.test.js +0 -272
  39. package/test/legacy-operator-compat.test.js +0 -154
  40. package/test/query-operators.test.js +0 -238
  41. package/test/regex-array-fields.test.js +0 -129
  42. package/test/score-method.test.js +0 -298
  43. package/test/setup.js +0 -17
  44. package/test/term-mapping-minimal.test.js +0 -154
  45. package/test/term-mapping-simple.test.js +0 -257
  46. package/test/term-mapping.test.js +0 -514
  47. package/test/writebuffer-flush-resilience.test.js +0 -204
@@ -1,154 +0,0 @@
1
- import { Database } from '../src/Database.mjs'
2
- import fs from 'fs'
3
-
4
- describe('Legacy operator compatibility', () => {
5
- let testDbPath
6
- let testIdxPath
7
-
8
- beforeEach(() => {
9
- const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).slice(2)}`
10
- testDbPath = `test-legacy-operators-${uniqueSuffix}.jdb`
11
- testIdxPath = testDbPath.replace('.jdb', '.idx.jdb')
12
- })
13
-
14
- afterEach(() => {
15
- for (const filePath of [testDbPath, testIdxPath]) {
16
- if (filePath && fs.existsSync(filePath)) {
17
- try {
18
- fs.unlinkSync(filePath)
19
- } catch (error) {
20
- console.warn(`⚠️ Failed to delete ${filePath}: ${error.message}`)
21
- }
22
- }
23
- }
24
- })
25
-
26
- test('should support string comparison operators for find/count', async () => {
27
- const db = new Database(testDbPath, {
28
- indexes: {
29
- start: 'number',
30
- end: 'number'
31
- },
32
- termMapping: true,
33
- debugMode: false
34
- })
35
- await db.init()
36
-
37
- const now = Math.floor(Date.now() / 1000)
38
-
39
- await db.insert({
40
- id: '1',
41
- start: now - 60,
42
- end: now + 60
43
- })
44
-
45
- await db.insert({
46
- id: '2',
47
- start: now - 3600,
48
- end: now - 300
49
- })
50
-
51
- const legacyCount = await db.count({ end: { '>': now } })
52
- const mongoCount = await db.count({ end: { $gt: now } })
53
- expect(legacyCount).toBe(1)
54
- expect(legacyCount).toBe(mongoCount)
55
-
56
- const legacyResults = await db.find({
57
- start: { '<=': now },
58
- end: { '>': now }
59
- })
60
- const canonicalResults = await db.find({
61
- start: { $lte: now },
62
- end: { $gt: now }
63
- })
64
- const mongoResults = await db.find({
65
- start: { $lte: now },
66
- end: { $gt: now }
67
- })
68
-
69
- expect(legacyResults.map(record => record.id)).toEqual(['1'])
70
- expect(canonicalResults.map(record => record.id)).toEqual(['1'])
71
- expect(mongoResults.map(record => record.id)).toEqual(['1'])
72
-
73
- await db.save()
74
- await db.destroy()
75
- })
76
-
77
- test('should support string inequality operator', async () => {
78
- const db = new Database(testDbPath, {
79
- indexes: {
80
- end: 'number'
81
- },
82
- termMapping: true,
83
- debugMode: false
84
- })
85
- await db.init()
86
-
87
- const now = Math.floor(Date.now() / 1000)
88
-
89
- await db.insert({
90
- id: 'A',
91
- end: now + 120
92
- })
93
-
94
- await db.insert({
95
- id: 'B',
96
- end: now + 240
97
- })
98
-
99
- const legacyResults = await db.find({
100
- end: { '!=': now + 120 }
101
- })
102
-
103
- expect(legacyResults.map(record => record.id)).toEqual(['B'])
104
-
105
- await db.save()
106
- await db.destroy()
107
- })
108
-
109
- test('should support mongo-style comparison operators when using indexes', async () => {
110
- const db = new Database(testDbPath, {
111
- indexes: {
112
- numericField: 'number'
113
- },
114
- debugMode: false
115
- })
116
- await db.init()
117
-
118
- await db.insert({ id: '10', numericField: 100 })
119
- await db.insert({ id: '20', numericField: 200 })
120
-
121
- await db.save()
122
- await db.close()
123
-
124
- const reopenedDb = new Database(testDbPath, {
125
- create: false,
126
- indexes: {
127
- numericField: 'number'
128
- },
129
- debugMode: false
130
- })
131
- await reopenedDb.init()
132
-
133
- const greaterThanResults = await reopenedDb.find({ numericField: { $gt: 150 } })
134
- expect(greaterThanResults.map(record => record.id)).toEqual(['20'])
135
-
136
- const greaterOrEqualResults = await reopenedDb.find({ numericField: { $gte: 200 } })
137
- expect(greaterOrEqualResults.map(record => record.id)).toEqual(['20'])
138
-
139
- const lessThanResults = await reopenedDb.find({ numericField: { $lt: 150 } })
140
- expect(lessThanResults.map(record => record.id)).toEqual(['10'])
141
-
142
- const lessOrEqualResults = await reopenedDb.find({ numericField: { $lte: 100 } })
143
- expect(lessOrEqualResults.map(record => record.id)).toEqual(['10'])
144
-
145
- const notEqualResults = await reopenedDb.find({ numericField: { $ne: 100 } })
146
- expect(notEqualResults.map(record => record.id)).toEqual(['20'])
147
-
148
- const countResults = await reopenedDb.count({ numericField: { $gt: 50, $lt: 250 } })
149
- expect(countResults).toBe(2)
150
-
151
- await reopenedDb.destroy()
152
- })
153
- })
154
-
@@ -1,238 +0,0 @@
1
- /**
2
- * Comprehensive tests for query operators
3
- * Tests the fixes for the $not operator and default operator behavior bugs
4
- */
5
-
6
- import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
7
- import Database from '../src/Database.mjs';
8
- import fs from 'fs';
9
- import path from 'path';
10
-
11
- describe('Query Operators', () => {
12
- let db;
13
- const testDbPath = 'test-query-operators-comprehensive';
14
-
15
- beforeEach(async () => {
16
- // Clean up any existing test database
17
- if (fs.existsSync(testDbPath + '.jdb')) {
18
- fs.unlinkSync(testDbPath + '.jdb');
19
- }
20
- if (fs.existsSync(testDbPath + '.terms.jdb')) {
21
- fs.unlinkSync(testDbPath + '.terms.jdb');
22
- }
23
-
24
- db = new Database(testDbPath, {
25
- debugMode: false,
26
- termMapping: true,
27
- termMappingFields: ['nameTerms', 'tags']
28
- });
29
-
30
- await db.init();
31
-
32
- // Insert comprehensive test data
33
- const testData = [
34
- { id: 1, name: 'TV Câmara', nameTerms: ['tv', 'câmara'], tags: ['news', 'politics'], group: 'Brazil', rating: 4.5 },
35
- { id: 2, name: 'TV Cultura', nameTerms: ['tv', 'cultura'], tags: ['culture', 'education'], group: 'Brazil', rating: 4.2 },
36
- { id: 3, name: 'SBT', nameTerms: ['sbt'], tags: ['entertainment'], group: 'Brazil', rating: 3.8 },
37
- { id: 4, name: 'Record News', nameTerms: ['record', 'news'], tags: ['news'], group: 'Brazil', rating: 4.0 },
38
- { id: 5, name: 'CNN', nameTerms: ['cnn'], tags: ['news', 'international'], group: 'International', rating: 4.7 },
39
- { id: 6, name: 'BBC', nameTerms: ['bbc'], tags: ['news', 'international'], group: 'International', rating: 4.6 },
40
- { id: 7, name: 'TV Globo', nameTerms: ['tv', 'globo'], tags: ['entertainment', 'news'], group: 'Brazil', rating: 4.3 },
41
- { id: 8, name: 'TV Record', nameTerms: ['tv', 'record'], tags: ['entertainment'], group: 'Brazil', rating: 3.9 },
42
- { id: 9, name: 'Discovery', nameTerms: ['discovery'], tags: ['documentary', 'education'], group: 'International', rating: 4.4 },
43
- { id: 10, name: 'National Geographic', nameTerms: ['national', 'geographic'], tags: ['documentary', 'nature'], group: 'International', rating: 4.8 }
44
- ];
45
-
46
- for (const record of testData) {
47
- await db.insert(record);
48
- }
49
- });
50
-
51
- afterEach(async () => {
52
- if (db) {
53
- await db.close();
54
- }
55
-
56
- // Clean up test files
57
- const files = [testDbPath + '.jdb', testDbPath + '.terms.jdb'];
58
- for (const file of files) {
59
- if (fs.existsSync(file)) {
60
- fs.unlinkSync(file);
61
- }
62
- }
63
- });
64
-
65
- describe('$not Operator Fixes', () => {
66
- it('should handle $not operator consistently with or without explicit $and', async () => {
67
- // Test 1: $not without explicit $and (the bug case)
68
- const result1 = await db.find({nameTerms: 'tv', $not: {nameTerms: { $in: ['cultura'] }}});
69
- expect(result1).toHaveLength(3); // TV Câmara, TV Globo, TV Record
70
- expect(result1.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'TV Globo', 'TV Record']));
71
- expect(result1.map(r => r.name)).not.toContain('TV Cultura');
72
-
73
- // Test 2: $not with explicit $and (should give same result)
74
- const result2 = await db.find({"$and": [{nameTerms: 'tv'}, {$not: {nameTerms: { $in: ['cultura'] }}}]});
75
- expect(result2).toHaveLength(3);
76
- expect(result2.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'TV Globo', 'TV Record']));
77
- expect(result2.map(r => r.name)).not.toContain('TV Cultura');
78
-
79
- // Both results should be identical
80
- expect(result1.map(r => r.id).sort()).toEqual(result2.map(r => r.id).sort());
81
- });
82
-
83
- it('should handle $not with different fields', async () => {
84
- const result = await db.find({group: 'Brazil', $not: {nameTerms: { $in: ['globo'] }}});
85
- expect(result).toHaveLength(5); // All Brazil channels except TV Globo
86
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'TV Cultura', 'SBT', 'Record News', 'TV Record']));
87
- expect(result.map(r => r.name)).not.toContain('TV Globo');
88
- });
89
-
90
- it('should handle complex $not queries', async () => {
91
- const result = await db.find({nameTerms: 'tv', $not: {nameTerms: { $in: ['cultura', 'globo'] }}});
92
- expect(result).toHaveLength(2); // TV Câmara, TV Record
93
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'TV Record']));
94
- expect(result.map(r => r.name)).not.toContain('TV Cultura');
95
- expect(result.map(r => r.name)).not.toContain('TV Globo');
96
- });
97
-
98
- it('should handle $not with numeric comparisons', async () => {
99
- const result = await db.find({group: 'Brazil', $not: {rating: { $gte: 4.0 }}});
100
- expect(result).toHaveLength(2); // SBT (3.8), TV Record (3.9)
101
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['SBT', 'TV Record']));
102
- });
103
-
104
- it('should handle nested $not operators', async () => {
105
- const result = await db.find({$not: {nameTerms: { $in: ['tv'] }}});
106
- expect(result).toHaveLength(6); // All channels without 'tv' in nameTerms
107
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['SBT', 'Record News', 'CNN', 'BBC', 'Discovery', 'National Geographic']));
108
- expect(result.map(r => r.name)).not.toContain('TV Câmara');
109
- expect(result.map(r => r.name)).not.toContain('TV Cultura');
110
- expect(result.map(r => r.name)).not.toContain('TV Globo');
111
- expect(result.map(r => r.name)).not.toContain('TV Record');
112
- });
113
- });
114
-
115
- describe('Default Operator Behavior (AND Logic)', () => {
116
- it('should use AND logic for multiple conditions at root level', async () => {
117
- const result = await db.find({nameTerms: 'tv', group: 'Brazil'});
118
- expect(result).toHaveLength(4); // All TV channels in Brazil
119
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'TV Cultura', 'TV Globo', 'TV Record']));
120
- });
121
-
122
- it('should use AND logic for multiple field conditions', async () => {
123
- const result = await db.find({group: 'International', rating: { $gte: 4.5 }});
124
- expect(result).toHaveLength(3); // CNN, BBC, National Geographic
125
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['CNN', 'BBC', 'National Geographic']));
126
- });
127
-
128
- it('should use AND logic with array field conditions', async () => {
129
- const result = await db.find({tags: { $in: ['news'] }, group: 'Brazil'});
130
- expect(result).toHaveLength(3); // TV Câmara, Record News, TV Globo
131
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'Record News', 'TV Globo']));
132
- });
133
-
134
- it('should use AND logic with mixed operators', async () => {
135
- const result = await db.find({
136
- nameTerms: 'tv',
137
- group: 'Brazil',
138
- rating: { $gte: 4.0 },
139
- tags: { $in: ['news'] }
140
- });
141
- expect(result).toHaveLength(2); // TV Câmara, TV Globo
142
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'TV Globo']));
143
- });
144
- });
145
-
146
- describe('Complex Query Combinations', () => {
147
- it('should handle $and with $not', async () => {
148
- const result = await db.find({
149
- "$and": [
150
- {group: 'Brazil'},
151
- {$not: {nameTerms: { $in: ['cultura', 'globo'] }}}
152
- ]
153
- });
154
- expect(result).toHaveLength(4); // All Brazil channels except TV Cultura and TV Globo
155
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'SBT', 'Record News', 'TV Record']));
156
- });
157
-
158
- it('should handle $or with $not', async () => {
159
- const result = await db.find({
160
- "$or": [
161
- {nameTerms: 'tv'},
162
- {group: 'International'}
163
- ],
164
- $not: {rating: { $lt: 4.0 }}
165
- });
166
- // Should include TV channels with rating >= 4.0 OR International channels with rating >= 4.0
167
- expect(result.length).toBeGreaterThan(0);
168
- result.forEach(record => {
169
- expect(record.rating).toBeGreaterThanOrEqual(4.0);
170
- });
171
- });
172
-
173
- it('should handle multiple $not conditions', async () => {
174
- // Note: Multiple $not conditions with the same key will overwrite each other
175
- // This is expected JavaScript behavior. For multiple conditions, use $and
176
- const result = await db.find({
177
- "$and": [
178
- {group: 'Brazil'},
179
- {$not: {nameTerms: { $in: ['cultura'] }}},
180
- {$not: {rating: { $lt: 4.0 }}}
181
- ]
182
- });
183
- // This should be equivalent to: Brazil AND NOT cultura AND NOT rating < 4.0
184
- expect(result.length).toBeGreaterThan(0);
185
- result.forEach(record => {
186
- expect(record.group).toBe('Brazil');
187
- expect(record.nameTerms).not.toContain('cultura');
188
- expect(record.rating).toBeGreaterThanOrEqual(4.0);
189
- });
190
- });
191
- });
192
-
193
- describe('Edge Cases', () => {
194
- it('should handle empty $not condition', async () => {
195
- const result = await db.find({nameTerms: 'tv', $not: {}});
196
- expect(result).toHaveLength(4); // All TV channels (empty $not matches nothing, so excludes nothing)
197
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'TV Cultura', 'TV Globo', 'TV Record']));
198
- });
199
-
200
- it('should handle $not with non-existent field', async () => {
201
- const result = await db.find({nameTerms: 'tv', $not: {nonExistentField: 'value'}});
202
- expect(result).toHaveLength(4); // All TV channels (non-existent field never matches)
203
- expect(result.map(r => r.name)).toEqual(expect.arrayContaining(['TV Câmara', 'TV Cultura', 'TV Globo', 'TV Record']));
204
- });
205
-
206
- it('should handle $not with null values', async () => {
207
- // Insert a record with null value
208
- await db.insert({ id: 99, name: 'Test Channel', nameTerms: null, group: 'Test' });
209
-
210
- const result = await db.find({group: 'Test', $not: {nameTerms: null}});
211
- expect(result).toHaveLength(0); // No records match (the only Test record has null nameTerms)
212
- });
213
- });
214
-
215
- describe('Performance and Consistency', () => {
216
- it('should produce consistent results across multiple queries', async () => {
217
- const query = {nameTerms: 'tv', $not: {nameTerms: { $in: ['cultura'] }}};
218
-
219
- // Run the same query multiple times
220
- const results = [];
221
- for (let i = 0; i < 5; i++) {
222
- const result = await db.find(query);
223
- results.push(result.map(r => r.id).sort());
224
- }
225
-
226
- // All results should be identical
227
- for (let i = 1; i < results.length; i++) {
228
- expect(results[i]).toEqual(results[0]);
229
- }
230
- });
231
-
232
- it('should handle large result sets with $not', async () => {
233
- // This test ensures the fix works with larger datasets
234
- const result = await db.find({$not: {group: 'NonExistent'}});
235
- expect(result).toHaveLength(10); // All records (since no records have group 'NonExistent')
236
- });
237
- });
238
- });
@@ -1,129 +0,0 @@
1
- import { describe, test, expect, beforeEach, afterEach } from '@jest/globals'
2
- import { Database } from '../src/Database.mjs'
3
- import path from 'path'
4
-
5
- describe('RegExp Queries on Array Fields', () => {
6
- let testDir
7
- let db
8
-
9
- beforeEach(async () => {
10
- testDir = path.join(process.cwd(), 'test-dbs')
11
- })
12
-
13
- afterEach(async () => {
14
- if (db) {
15
- await db.save()
16
- await db.destroy()
17
- db = null
18
- }
19
- })
20
-
21
- describe('Bug Fix: RegExp on Array Fields', () => {
22
- test('should correctly filter array fields with RegExp queries', async () => {
23
- const dbPath = path.join(testDir, 'regex-array-fields.jdb')
24
-
25
- db = new Database(dbPath, {
26
- clear: true,
27
- create: true,
28
- debugMode: false
29
- })
30
-
31
- await db.init()
32
-
33
- // Insert test data
34
- await db.insert({ name: 'Globo', nameTerms: ['globo'] })
35
- await db.insert({ name: 'FlixHD', nameTerms: ['flixhd'] })
36
- await db.insert({ name: 'Netflix', nameTerms: ['netflix'] })
37
- await db.insert({ name: 'Global News', nameTerms: ['global', 'news'] })
38
-
39
- // Test 1: RegExp query that should match multiple records
40
- const results1 = await db.find({ nameTerms: new RegExp('glob', 'i') })
41
- expect(results1.length).toBe(2)
42
- expect(results1.some(r => r.name === 'Globo')).toBe(true)
43
- expect(results1.some(r => r.name === 'Global News')).toBe(true)
44
-
45
- // Test 2: RegExp query with impossible pattern
46
- const results2 = await db.find({ nameTerms: new RegExp('IMPOSSIBLE_PATTERN_12345', 'i') })
47
- expect(results2.length).toBe(0)
48
-
49
- // Test 3: RegExp query that matches multiple records with "flix"
50
- const results3 = await db.find({ nameTerms: new RegExp('flix', 'i') })
51
- expect(results3.length).toBe(2)
52
- expect(results3.some(r => r.name === 'FlixHD')).toBe(true)
53
- expect(results3.some(r => r.name === 'Netflix')).toBe(true)
54
-
55
- // Test 4: RegExp query with anchor (start of string)
56
- const results4 = await db.find({ nameTerms: new RegExp('^flix', 'i') })
57
- expect(results4.length).toBe(1)
58
- expect(results4[0].name).toBe('FlixHD')
59
-
60
- // Test 5: RegExp query with case sensitivity
61
- const results5 = await db.find({ nameTerms: new RegExp('GLOBO') })
62
- expect(results5.length).toBe(0) // Should not match because it's case-sensitive
63
-
64
- const results6 = await db.find({ nameTerms: new RegExp('GLOBO', 'i') })
65
- expect(results6.length).toBe(1) // Should match because it's case-insensitive
66
- expect(results6[0].name).toBe('Globo')
67
- })
68
-
69
- test('should correctly handle RegExp queries with multi-element arrays', async () => {
70
- const dbPath = path.join(testDir, 'regex-multi-array.jdb')
71
-
72
- db = new Database(dbPath, {
73
- clear: true,
74
- create: true,
75
- debugMode: false
76
- })
77
-
78
- await db.init()
79
-
80
- // Insert test data with multi-element arrays
81
- await db.insert({ name: 'Test 1', tags: ['javascript', 'nodejs', 'backend'] })
82
- await db.insert({ name: 'Test 2', tags: ['python', 'django', 'backend'] })
83
- await db.insert({ name: 'Test 3', tags: ['javascript', 'react', 'frontend'] })
84
- await db.insert({ name: 'Test 4', tags: ['ruby', 'rails', 'backend'] })
85
-
86
- // Test: RegExp query that matches first element
87
- const results1 = await db.find({ tags: new RegExp('java', 'i') })
88
- expect(results1.length).toBe(2)
89
- expect(results1.some(r => r.name === 'Test 1')).toBe(true)
90
- expect(results1.some(r => r.name === 'Test 3')).toBe(true)
91
-
92
- // Test: RegExp query that matches middle element
93
- const results2 = await db.find({ tags: new RegExp('react', 'i') })
94
- expect(results2.length).toBe(1)
95
- expect(results2[0].name).toBe('Test 3')
96
-
97
- // Test: RegExp query that matches last element
98
- const results3 = await db.find({ tags: new RegExp('backend', 'i') })
99
- expect(results3.length).toBe(3)
100
- expect(results3.some(r => r.name === 'Test 1')).toBe(true)
101
- expect(results3.some(r => r.name === 'Test 2')).toBe(true)
102
- expect(results3.some(r => r.name === 'Test 4')).toBe(true)
103
- })
104
-
105
- test('should correctly handle $regex operator on array fields', async () => {
106
- const dbPath = path.join(testDir, 'regex-operator-array.jdb')
107
-
108
- db = new Database(dbPath, {
109
- clear: true,
110
- create: true,
111
- debugMode: false
112
- })
113
-
114
- await db.init()
115
-
116
- // Insert test data
117
- await db.insert({ name: 'Globo', nameTerms: ['globo'] })
118
- await db.insert({ name: 'FlixHD', nameTerms: ['flixhd'] })
119
- await db.insert({ name: 'Netflix', nameTerms: ['netflix'] })
120
- await db.insert({ name: 'Global News', nameTerms: ['global', 'news'] })
121
-
122
- // Test: $regex operator query
123
- const results = await db.find({ nameTerms: { $regex: 'glob' } })
124
- expect(results.length).toBe(2)
125
- expect(results.some(r => r.name === 'Globo')).toBe(true)
126
- expect(results.some(r => r.name === 'Global News')).toBe(true)
127
- })
128
- })
129
- })