@joystick.js/db-canary 0.0.0-canary.2250 → 0.0.0-canary.2251
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/dist/server/lib/operations/find.js +1 -1
- package/dist/server/lib/operations/find_one.js +1 -1
- package/package.json +2 -2
- package/src/server/lib/operations/find.js +144 -15
- package/src/server/lib/operations/find_one.js +144 -14
- package/test_data_api_key_1758233848259_cglfjzhou/data.mdb +0 -0
- package/test_data_api_key_1758233848259_cglfjzhou/lock.mdb +0 -0
- package/test_data_api_key_1758233848502_urlje2utd/data.mdb +0 -0
- package/test_data_api_key_1758233848502_urlje2utd/lock.mdb +0 -0
- package/test_data_api_key_1758233848738_mtcpfe5ns/data.mdb +0 -0
- package/test_data_api_key_1758233848738_mtcpfe5ns/lock.mdb +0 -0
- package/test_data_api_key_1758233848856_9g97p6gag/data.mdb +0 -0
- package/test_data_api_key_1758233848856_9g97p6gag/lock.mdb +0 -0
- package/test_data_api_key_1758233857008_0tl9zzhj8/data.mdb +0 -0
- package/test_data_api_key_1758233857008_0tl9zzhj8/lock.mdb +0 -0
- package/test_data_api_key_1758233857120_60c2f2uhu/data.mdb +0 -0
- package/test_data_api_key_1758233857120_60c2f2uhu/lock.mdb +0 -0
- package/test_data_api_key_1758233857232_aw7fkqgd9/data.mdb +0 -0
- package/test_data_api_key_1758233857232_aw7fkqgd9/lock.mdb +0 -0
- package/test_data_api_key_1758234881285_4aeflubjb/data.mdb +0 -0
- package/test_data_api_key_1758234881285_4aeflubjb/lock.mdb +0 -0
- package/test_data_api_key_1758234881520_kb0amvtqb/data.mdb +0 -0
- package/test_data_api_key_1758234881520_kb0amvtqb/lock.mdb +0 -0
- package/test_data_api_key_1758234881756_k04gfv2va/data.mdb +0 -0
- package/test_data_api_key_1758234881756_k04gfv2va/lock.mdb +0 -0
- package/test_data_api_key_1758234881876_wn90dpo1z/data.mdb +0 -0
- package/test_data_api_key_1758234881876_wn90dpo1z/lock.mdb +0 -0
- package/test_data_api_key_1758234889461_26xz3dmbr/data.mdb +0 -0
- package/test_data_api_key_1758234889461_26xz3dmbr/lock.mdb +0 -0
- package/test_data_api_key_1758234889572_uziz7e0p5/data.mdb +0 -0
- package/test_data_api_key_1758234889572_uziz7e0p5/lock.mdb +0 -0
- package/test_data_api_key_1758234889684_5f9wmposh/data.mdb +0 -0
- package/test_data_api_key_1758234889684_5f9wmposh/lock.mdb +0 -0
- package/test_data_api_key_1758235657729_prwgm6mxr/data.mdb +0 -0
- package/test_data_api_key_1758235657729_prwgm6mxr/lock.mdb +0 -0
- package/test_data_api_key_1758235657961_rc2da0dc2/data.mdb +0 -0
- package/test_data_api_key_1758235657961_rc2da0dc2/lock.mdb +0 -0
- package/test_data_api_key_1758235658193_oqqxm0sny/data.mdb +0 -0
- package/test_data_api_key_1758235658193_oqqxm0sny/lock.mdb +0 -0
- package/test_data_api_key_1758235658309_vggac1pj6/data.mdb +0 -0
- package/test_data_api_key_1758235658309_vggac1pj6/lock.mdb +0 -0
- package/test_data_api_key_1758235665968_61ko07dd1/data.mdb +0 -0
- package/test_data_api_key_1758235665968_61ko07dd1/lock.mdb +0 -0
- package/test_data_api_key_1758235666082_50lrt6sq8/data.mdb +0 -0
- package/test_data_api_key_1758235666082_50lrt6sq8/lock.mdb +0 -0
- package/test_data_api_key_1758235666194_ykvauwlzh/data.mdb +0 -0
- package/test_data_api_key_1758235666194_ykvauwlzh/lock.mdb +0 -0
- package/test_data_api_key_1758236187207_9c4paeh09/data.mdb +0 -0
- package/test_data_api_key_1758236187207_9c4paeh09/lock.mdb +0 -0
- package/test_data_api_key_1758236187441_4n3o3gkkl/data.mdb +0 -0
- package/test_data_api_key_1758236187441_4n3o3gkkl/lock.mdb +0 -0
- package/test_data_api_key_1758236187672_jt6b21ye0/data.mdb +0 -0
- package/test_data_api_key_1758236187672_jt6b21ye0/lock.mdb +0 -0
- package/test_data_api_key_1758236187788_oo84fz9u6/data.mdb +0 -0
- package/test_data_api_key_1758236187788_oo84fz9u6/lock.mdb +0 -0
- package/test_data_api_key_1758236195507_o9zeznwlm/data.mdb +0 -0
- package/test_data_api_key_1758236195507_o9zeznwlm/lock.mdb +0 -0
- package/test_data_api_key_1758236195619_qsqd60y41/data.mdb +0 -0
- package/test_data_api_key_1758236195619_qsqd60y41/lock.mdb +0 -0
- package/test_data_api_key_1758236195731_im13iq284/data.mdb +0 -0
- package/test_data_api_key_1758236195731_im13iq284/lock.mdb +0 -0
- package/tests/server/cluster/master_read_write_operations.test.js +5 -14
- package/tests/server/integration/authentication_integration.test.js +18 -10
- package/tests/server/integration/backup_integration.test.js +35 -27
- package/tests/server/lib/api_key_manager.test.js +88 -32
- package/tests/server/lib/development_mode.test.js +2 -2
- package/tests/server/lib/operations/admin.test.js +20 -12
- package/tests/server/lib/operations/delete_one.test.js +10 -4
- package/tests/server/lib/operations/find_array_queries.test.js +261 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import find from '../../../../src/server/lib/operations/find.js';
|
|
3
|
+
import find_one from '../../../../src/server/lib/operations/find_one.js';
|
|
4
|
+
import insert_one from '../../../../src/server/lib/operations/insert_one.js';
|
|
5
|
+
import { initialize_database, get_database, cleanup_database } from '../../../../src/server/lib/query_engine.js';
|
|
6
|
+
|
|
7
|
+
test.beforeEach(() => {
|
|
8
|
+
initialize_database('./test_data');
|
|
9
|
+
const db = get_database();
|
|
10
|
+
db.clearSync();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test.afterEach(async (t) => {
|
|
14
|
+
await cleanup_database();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('find - should match array field with direct value', async (t) => {
|
|
18
|
+
await insert_one('default', 'products', {
|
|
19
|
+
name: 'MacBook Pro',
|
|
20
|
+
tags: ['laptop', 'apple', 'professional']
|
|
21
|
+
});
|
|
22
|
+
await insert_one('default', 'products', {
|
|
23
|
+
name: 'iPad Pro',
|
|
24
|
+
tags: ['tablet', 'apple', 'professional']
|
|
25
|
+
});
|
|
26
|
+
await insert_one('default', 'products', {
|
|
27
|
+
name: 'Dell XPS',
|
|
28
|
+
tags: ['laptop', 'dell', 'ultrabook']
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Test array field matching
|
|
32
|
+
const laptops = await find('default', 'products', { tags: 'laptop' });
|
|
33
|
+
t.is(laptops.length, 2);
|
|
34
|
+
t.true(laptops.some(doc => doc.name === 'MacBook Pro'));
|
|
35
|
+
t.true(laptops.some(doc => doc.name === 'Dell XPS'));
|
|
36
|
+
|
|
37
|
+
const apple_products = await find('default', 'products', { tags: 'apple' });
|
|
38
|
+
t.is(apple_products.length, 2);
|
|
39
|
+
t.true(apple_products.some(doc => doc.name === 'MacBook Pro'));
|
|
40
|
+
t.true(apple_products.some(doc => doc.name === 'iPad Pro'));
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('find - should match array field with $in operator', async (t) => {
|
|
44
|
+
await insert_one('default', 'products', {
|
|
45
|
+
name: 'MacBook Pro',
|
|
46
|
+
tags: ['laptop', 'apple', 'professional']
|
|
47
|
+
});
|
|
48
|
+
await insert_one('default', 'products', {
|
|
49
|
+
name: 'iPad Pro',
|
|
50
|
+
tags: ['tablet', 'apple', 'professional']
|
|
51
|
+
});
|
|
52
|
+
await insert_one('default', 'products', {
|
|
53
|
+
name: 'Dell XPS',
|
|
54
|
+
tags: ['laptop', 'dell', 'ultrabook']
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Test $in with array fields
|
|
58
|
+
const professional_products = await find('default', 'products', {
|
|
59
|
+
tags: { $in: ['professional'] }
|
|
60
|
+
});
|
|
61
|
+
t.is(professional_products.length, 2);
|
|
62
|
+
t.true(professional_products.some(doc => doc.name === 'MacBook Pro'));
|
|
63
|
+
t.true(professional_products.some(doc => doc.name === 'iPad Pro'));
|
|
64
|
+
|
|
65
|
+
const mobile_products = await find('default', 'products', {
|
|
66
|
+
tags: { $in: ['laptop', 'tablet'] }
|
|
67
|
+
});
|
|
68
|
+
t.is(mobile_products.length, 3);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('find - should match nested array object queries', async (t) => {
|
|
72
|
+
await insert_one('default', 'products', {
|
|
73
|
+
name: 'MacBook Pro',
|
|
74
|
+
reviews: [
|
|
75
|
+
{ rating: 5, comment: 'Great laptop!' },
|
|
76
|
+
{ rating: 4, comment: 'Good value' }
|
|
77
|
+
]
|
|
78
|
+
});
|
|
79
|
+
await insert_one('default', 'products', {
|
|
80
|
+
name: 'iPad Pro',
|
|
81
|
+
reviews: [
|
|
82
|
+
{ rating: 5, comment: 'Perfect for drawing' },
|
|
83
|
+
{ rating: 5, comment: 'Amazing display' }
|
|
84
|
+
]
|
|
85
|
+
});
|
|
86
|
+
await insert_one('default', 'products', {
|
|
87
|
+
name: 'Dell XPS',
|
|
88
|
+
reviews: [
|
|
89
|
+
{ rating: 4, comment: 'Compact and powerful' }
|
|
90
|
+
]
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Test nested array object queries
|
|
94
|
+
const five_star_products = await find('default', 'products', { 'reviews.rating': 5 });
|
|
95
|
+
t.is(five_star_products.length, 2);
|
|
96
|
+
t.true(five_star_products.some(doc => doc.name === 'MacBook Pro'));
|
|
97
|
+
t.true(five_star_products.some(doc => doc.name === 'iPad Pro'));
|
|
98
|
+
|
|
99
|
+
const four_star_products = await find('default', 'products', { 'reviews.rating': 4 });
|
|
100
|
+
t.is(four_star_products.length, 2);
|
|
101
|
+
t.true(four_star_products.some(doc => doc.name === 'MacBook Pro'));
|
|
102
|
+
t.true(four_star_products.some(doc => doc.name === 'Dell XPS'));
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('find - should match nested object queries', async (t) => {
|
|
106
|
+
await insert_one('default', 'products', {
|
|
107
|
+
name: 'MacBook Pro',
|
|
108
|
+
specs: { ram: 16, storage: 512, processor: 'M2 Pro' }
|
|
109
|
+
});
|
|
110
|
+
await insert_one('default', 'products', {
|
|
111
|
+
name: 'iPad Pro',
|
|
112
|
+
specs: { ram: 8, storage: 128, processor: 'M2' }
|
|
113
|
+
});
|
|
114
|
+
await insert_one('default', 'products', {
|
|
115
|
+
name: 'Dell XPS',
|
|
116
|
+
specs: { ram: 16, storage: 256, processor: 'Intel i7' }
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Test nested object queries
|
|
120
|
+
const high_ram_products = await find('default', 'products', { 'specs.ram': { $gte: 16 } });
|
|
121
|
+
t.is(high_ram_products.length, 2);
|
|
122
|
+
t.true(high_ram_products.some(doc => doc.name === 'MacBook Pro'));
|
|
123
|
+
t.true(high_ram_products.some(doc => doc.name === 'Dell XPS'));
|
|
124
|
+
|
|
125
|
+
const m2_products = await find('default', 'products', { 'specs.processor': { $regex: 'M2' } });
|
|
126
|
+
t.is(m2_products.length, 2);
|
|
127
|
+
t.true(m2_products.some(doc => doc.name === 'MacBook Pro'));
|
|
128
|
+
t.true(m2_products.some(doc => doc.name === 'iPad Pro'));
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('find - should handle complex $or queries with arrays', async (t) => {
|
|
132
|
+
await insert_one('default', 'products', {
|
|
133
|
+
name: 'MacBook Pro',
|
|
134
|
+
brand: 'Apple',
|
|
135
|
+
tags: ['laptop', 'professional'],
|
|
136
|
+
specs: { ram: 16 }
|
|
137
|
+
});
|
|
138
|
+
await insert_one('default', 'products', {
|
|
139
|
+
name: 'iPad Pro',
|
|
140
|
+
brand: 'Apple',
|
|
141
|
+
tags: ['tablet', 'professional'],
|
|
142
|
+
specs: { ram: 8 }
|
|
143
|
+
});
|
|
144
|
+
await insert_one('default', 'products', {
|
|
145
|
+
name: 'Dell XPS',
|
|
146
|
+
brand: 'Dell',
|
|
147
|
+
tags: ['laptop', 'ultrabook'],
|
|
148
|
+
specs: { ram: 16 }
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Test complex $or with array and nested queries
|
|
152
|
+
const complex_query = await find('default', 'products', {
|
|
153
|
+
$or: [
|
|
154
|
+
{ brand: 'Apple' },
|
|
155
|
+
{ 'specs.ram': { $gte: 16 } }
|
|
156
|
+
]
|
|
157
|
+
});
|
|
158
|
+
t.is(complex_query.length, 3); // All products match either condition
|
|
159
|
+
|
|
160
|
+
const array_or_query = await find('default', 'products', {
|
|
161
|
+
$or: [
|
|
162
|
+
{ tags: 'professional' },
|
|
163
|
+
{ tags: 'ultrabook' }
|
|
164
|
+
]
|
|
165
|
+
});
|
|
166
|
+
t.is(array_or_query.length, 3); // All products have either tag
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test('find_one - should work with array field matching', async (t) => {
|
|
170
|
+
await insert_one('default', 'products', {
|
|
171
|
+
name: 'MacBook Pro',
|
|
172
|
+
tags: ['laptop', 'apple', 'professional']
|
|
173
|
+
});
|
|
174
|
+
await insert_one('default', 'products', {
|
|
175
|
+
name: 'iPad Pro',
|
|
176
|
+
tags: ['tablet', 'apple', 'professional']
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Test find_one with array field
|
|
180
|
+
const apple_product = await find_one('default', 'products', { tags: 'apple' });
|
|
181
|
+
t.truthy(apple_product);
|
|
182
|
+
t.true(['MacBook Pro', 'iPad Pro'].includes(apple_product.name));
|
|
183
|
+
|
|
184
|
+
const laptop_product = await find_one('default', 'products', { tags: 'laptop' });
|
|
185
|
+
t.truthy(laptop_product);
|
|
186
|
+
t.is(laptop_product.name, 'MacBook Pro');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test('find_one - should work with nested array object queries', async (t) => {
|
|
190
|
+
await insert_one('default', 'products', {
|
|
191
|
+
name: 'MacBook Pro',
|
|
192
|
+
reviews: [
|
|
193
|
+
{ rating: 5, comment: 'Great laptop!' },
|
|
194
|
+
{ rating: 4, comment: 'Good value' }
|
|
195
|
+
]
|
|
196
|
+
});
|
|
197
|
+
await insert_one('default', 'products', {
|
|
198
|
+
name: 'Dell XPS',
|
|
199
|
+
reviews: [
|
|
200
|
+
{ rating: 4, comment: 'Compact and powerful' }
|
|
201
|
+
]
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Test find_one with nested array object query
|
|
205
|
+
const five_star_product = await find_one('default', 'products', { 'reviews.rating': 5 });
|
|
206
|
+
t.truthy(five_star_product);
|
|
207
|
+
t.is(five_star_product.name, 'MacBook Pro');
|
|
208
|
+
|
|
209
|
+
const four_star_product = await find_one('default', 'products', { 'reviews.rating': 4 });
|
|
210
|
+
t.truthy(four_star_product);
|
|
211
|
+
t.true(['MacBook Pro', 'Dell XPS'].includes(four_star_product.name));
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test('find - should handle array fields with comparison operators', async (t) => {
|
|
215
|
+
await insert_one('default', 'products', {
|
|
216
|
+
name: 'Product A',
|
|
217
|
+
ratings: [1, 2, 3, 4, 5]
|
|
218
|
+
});
|
|
219
|
+
await insert_one('default', 'products', {
|
|
220
|
+
name: 'Product B',
|
|
221
|
+
ratings: [3, 4, 5]
|
|
222
|
+
});
|
|
223
|
+
await insert_one('default', 'products', {
|
|
224
|
+
name: 'Product C',
|
|
225
|
+
ratings: [1, 2]
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Test array fields with comparison operators
|
|
229
|
+
const high_rated = await find('default', 'products', { ratings: { $gte: 4 } });
|
|
230
|
+
t.is(high_rated.length, 2);
|
|
231
|
+
t.true(high_rated.some(doc => doc.name === 'Product A'));
|
|
232
|
+
t.true(high_rated.some(doc => doc.name === 'Product B'));
|
|
233
|
+
|
|
234
|
+
const low_rated = await find('default', 'products', { ratings: { $lte: 2 } });
|
|
235
|
+
t.is(low_rated.length, 2);
|
|
236
|
+
t.true(low_rated.some(doc => doc.name === 'Product A'));
|
|
237
|
+
t.true(low_rated.some(doc => doc.name === 'Product C'));
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test('find - should handle empty arrays correctly', async (t) => {
|
|
241
|
+
await insert_one('default', 'products', {
|
|
242
|
+
name: 'Product A',
|
|
243
|
+
tags: ['laptop', 'apple']
|
|
244
|
+
});
|
|
245
|
+
await insert_one('default', 'products', {
|
|
246
|
+
name: 'Product B',
|
|
247
|
+
tags: []
|
|
248
|
+
});
|
|
249
|
+
await insert_one('default', 'products', {
|
|
250
|
+
name: 'Product C'
|
|
251
|
+
// No tags field
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Test queries with empty arrays
|
|
255
|
+
const laptop_products = await find('default', 'products', { tags: 'laptop' });
|
|
256
|
+
t.is(laptop_products.length, 1);
|
|
257
|
+
t.is(laptop_products[0].name, 'Product A');
|
|
258
|
+
|
|
259
|
+
const no_match = await find('default', 'products', { tags: 'nonexistent' });
|
|
260
|
+
t.is(no_match.length, 0);
|
|
261
|
+
});
|