@onchaindb/sdk 0.4.4 → 1.0.0

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 (97) hide show
  1. package/.claude/settings.local.json +10 -2
  2. package/README.md +422 -355
  3. package/dist/batch.d.ts +1 -10
  4. package/dist/batch.d.ts.map +1 -1
  5. package/dist/batch.js +4 -26
  6. package/dist/batch.js.map +1 -1
  7. package/dist/client.d.ts +29 -43
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +199 -323
  10. package/dist/client.js.map +1 -1
  11. package/dist/database.d.ts +14 -131
  12. package/dist/database.d.ts.map +1 -1
  13. package/dist/database.js +35 -131
  14. package/dist/database.js.map +1 -1
  15. package/dist/index.d.ts +6 -9
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +1 -15
  18. package/dist/index.js.map +1 -1
  19. package/dist/query-sdk/ConditionBuilder.d.ts +3 -11
  20. package/dist/query-sdk/ConditionBuilder.d.ts.map +1 -1
  21. package/dist/query-sdk/ConditionBuilder.js +10 -48
  22. package/dist/query-sdk/ConditionBuilder.js.map +1 -1
  23. package/dist/query-sdk/NestedBuilders.d.ts +33 -30
  24. package/dist/query-sdk/NestedBuilders.d.ts.map +1 -1
  25. package/dist/query-sdk/NestedBuilders.js +46 -43
  26. package/dist/query-sdk/NestedBuilders.js.map +1 -1
  27. package/dist/query-sdk/QueryBuilder.d.ts +4 -2
  28. package/dist/query-sdk/QueryBuilder.d.ts.map +1 -1
  29. package/dist/query-sdk/QueryBuilder.js +47 -169
  30. package/dist/query-sdk/QueryBuilder.js.map +1 -1
  31. package/dist/query-sdk/QueryResult.d.ts +0 -38
  32. package/dist/query-sdk/QueryResult.d.ts.map +1 -1
  33. package/dist/query-sdk/QueryResult.js +1 -227
  34. package/dist/query-sdk/QueryResult.js.map +1 -1
  35. package/dist/query-sdk/index.d.ts +1 -1
  36. package/dist/query-sdk/index.d.ts.map +1 -1
  37. package/dist/query-sdk/index.js.map +1 -1
  38. package/dist/query-sdk/operators.d.ts +32 -28
  39. package/dist/query-sdk/operators.d.ts.map +1 -1
  40. package/dist/query-sdk/operators.js +45 -155
  41. package/dist/query-sdk/operators.js.map +1 -1
  42. package/dist/types.d.ts +153 -1
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/types.js.map +1 -1
  45. package/jest.config.js +4 -0
  46. package/package.json +1 -1
  47. package/skills.md +0 -1
  48. package/src/client.ts +243 -745
  49. package/src/database.ts +70 -493
  50. package/src/index.ts +40 -193
  51. package/src/query-sdk/ConditionBuilder.ts +37 -89
  52. package/src/query-sdk/NestedBuilders.ts +90 -92
  53. package/src/query-sdk/QueryBuilder.ts +59 -218
  54. package/src/query-sdk/QueryResult.ts +4 -330
  55. package/src/query-sdk/README.md +214 -583
  56. package/src/query-sdk/index.ts +1 -1
  57. package/src/query-sdk/operators.ts +91 -200
  58. package/src/query-sdk/tests/FieldConditionBuilder.test.ts +70 -71
  59. package/src/query-sdk/tests/LogicalOperator.test.ts +43 -82
  60. package/src/query-sdk/tests/NestedBuilders.test.ts +229 -309
  61. package/src/query-sdk/tests/QueryBuilder.test.ts +5 -5
  62. package/src/query-sdk/tests/QueryResult.test.ts +41 -435
  63. package/src/query-sdk/tests/comprehensive.test.ts +4 -185
  64. package/src/tests/client-requests.test.ts +280 -0
  65. package/src/tests/client-validation.test.ts +80 -0
  66. package/src/types.ts +229 -8
  67. package/src/batch.ts +0 -257
  68. package/src/query-sdk/dist/ConditionBuilder.d.ts +0 -22
  69. package/src/query-sdk/dist/ConditionBuilder.js +0 -90
  70. package/src/query-sdk/dist/FieldConditionBuilder.d.ts +0 -1
  71. package/src/query-sdk/dist/FieldConditionBuilder.js +0 -6
  72. package/src/query-sdk/dist/NestedBuilders.d.ts +0 -43
  73. package/src/query-sdk/dist/NestedBuilders.js +0 -144
  74. package/src/query-sdk/dist/OnChainDB.d.ts +0 -19
  75. package/src/query-sdk/dist/OnChainDB.js +0 -123
  76. package/src/query-sdk/dist/QueryBuilder.d.ts +0 -70
  77. package/src/query-sdk/dist/QueryBuilder.js +0 -295
  78. package/src/query-sdk/dist/QueryResult.d.ts +0 -52
  79. package/src/query-sdk/dist/QueryResult.js +0 -293
  80. package/src/query-sdk/dist/SelectionBuilder.d.ts +0 -20
  81. package/src/query-sdk/dist/SelectionBuilder.js +0 -80
  82. package/src/query-sdk/dist/adapters/HttpClientAdapter.d.ts +0 -27
  83. package/src/query-sdk/dist/adapters/HttpClientAdapter.js +0 -170
  84. package/src/query-sdk/dist/index.d.ts +0 -36
  85. package/src/query-sdk/dist/index.js +0 -27
  86. package/src/query-sdk/dist/operators.d.ts +0 -56
  87. package/src/query-sdk/dist/operators.js +0 -289
  88. package/src/query-sdk/dist/tests/setup.d.ts +0 -15
  89. package/src/query-sdk/dist/tests/setup.js +0 -46
  90. package/src/query-sdk/jest.config.js +0 -25
  91. package/src/query-sdk/package.json +0 -46
  92. package/src/query-sdk/tests/aggregations.test.ts +0 -653
  93. package/src/query-sdk/tests/integration.test.ts +0 -608
  94. package/src/query-sdk/tests/operators.test.ts +0 -327
  95. package/src/query-sdk/tests/unit.test.ts +0 -794
  96. package/src/query-sdk/tsconfig.json +0 -26
  97. package/src/query-sdk/yarn.lock +0 -3092
@@ -2,320 +2,240 @@ import { NestedConditionBuilder, NestedFieldConditionBuilder } from '../NestedBu
2
2
  import { LogicalOperator } from '../operators';
3
3
 
4
4
  describe('NestedConditionBuilder', () => {
5
- let nestedBuilder: NestedConditionBuilder;
6
-
7
- beforeEach(() => {
8
- nestedBuilder = new NestedConditionBuilder('user');
9
- });
10
-
11
- describe('Basic nested building', () => {
12
- test('should create nested field condition builder', () => {
13
- const fieldBuilder = nestedBuilder.field('name');
14
- expect(fieldBuilder).toBeInstanceOf(NestedFieldConditionBuilder);
15
- });
16
-
17
- test('should create condition with correct path', () => {
18
- const condition = nestedBuilder.field('name').equals('John');
19
- expect(condition.field).toBe('user.name');
20
- expect(condition.operator).toBe('is');
21
- expect(condition.value).toBe('John');
22
- });
23
-
24
- test('should handle multi-level nesting', () => {
25
- const condition = new NestedFieldConditionBuilder(['user', 'profile', 'bio']).contains('developer');
26
- expect(condition.field).toBe('user.profile.bio');
27
- expect(condition.operator).toBe('includes');
28
- expect(condition.value).toBe('developer');
29
- });
30
- });
31
-
32
- describe('Logical groups', () => {
33
- test('should create AND groups', () => {
34
- const andGroup = nestedBuilder.andGroup(builder => [
35
- LogicalOperator.Condition(builder.field('name').equals('John')),
36
- LogicalOperator.Condition(builder.field('age').greaterThan(25))
37
- ]);
38
-
39
- expect(andGroup.type).toBe('and');
40
- expect(andGroup.conditions).toHaveLength(2);
41
- });
42
-
43
- test('should create OR groups', () => {
44
- const orGroup = nestedBuilder.orGroup(builder => [
45
- LogicalOperator.Condition(builder.field('status').equals('active')),
46
- LogicalOperator.Condition(builder.field('status').equals('pending'))
47
- ]);
48
-
49
- expect(orGroup.type).toBe('or');
50
- expect(orGroup.conditions).toHaveLength(2);
51
- });
52
-
53
- test('should create NOT groups', () => {
54
- const notGroup = nestedBuilder.notGroup(builder => [
55
- LogicalOperator.Condition(builder.field('deleted').isTrue())
56
- ]);
57
-
58
- expect(notGroup.type).toBe('not');
59
- expect(notGroup.conditions).toHaveLength(1);
5
+ let nestedBuilder: NestedConditionBuilder;
6
+
7
+ beforeEach(() => {
8
+ nestedBuilder = new NestedConditionBuilder('user');
9
+ });
10
+
11
+ describe('Basic nested building', () => {
12
+ test('should create nested field condition builder', () => {
13
+ const fieldBuilder = nestedBuilder.field('name');
14
+ expect(fieldBuilder).toBeInstanceOf(NestedFieldConditionBuilder);
15
+ });
16
+
17
+ test('should create condition with correct path', () => {
18
+ const condition = nestedBuilder.field('name').equals('John');
19
+ expect(condition.toComposable()).toEqual({ user: { name: { is: 'John' } } });
20
+ });
21
+
22
+ test('should handle multi-level nesting', () => {
23
+ const condition = new NestedFieldConditionBuilder(['user', 'profile', 'bio']).contains('developer');
24
+ expect(condition.toComposable()).toEqual({ user: { profile: { bio: { includes: 'developer' } } } });
25
+ });
26
+ });
27
+
28
+ describe('Logical groups', () => {
29
+ test('should create AND groups', () => {
30
+ const andGroup = nestedBuilder.andGroup(builder => [
31
+ builder.field('name').equals('John'),
32
+ builder.field('age').greaterThan(25)
33
+ ]);
34
+ expect(andGroup.type).toBe('and');
35
+ expect(andGroup.conditions).toHaveLength(2);
36
+ });
37
+
38
+ test('should create OR groups', () => {
39
+ const orGroup = nestedBuilder.orGroup(builder => [
40
+ builder.field('status').equals('active'),
41
+ builder.field('status').equals('pending')
42
+ ]);
43
+ expect(orGroup.type).toBe('or');
44
+ expect(orGroup.conditions).toHaveLength(2);
45
+ });
46
+
47
+ test('should create NOT groups', () => {
48
+ const notGroup = nestedBuilder.notGroup(builder => [
49
+ builder.field('deleted').isTrue()
50
+ ]);
51
+ expect(notGroup.type).toBe('not');
52
+ expect(notGroup.conditions).toHaveLength(1);
53
+ });
54
+
55
+ test('variadic and/or/not methods', () => {
56
+ const and = nestedBuilder.and(
57
+ nestedBuilder.field('a').equals(1),
58
+ nestedBuilder.field('b').equals(2)
59
+ );
60
+ expect(and.type).toBe('and');
61
+ expect(and.conditions).toHaveLength(2);
62
+ });
63
+ });
64
+
65
+ describe('Nested structure creation', () => {
66
+ test('should create nested callback structure', () => {
67
+ const nested = nestedBuilder.nested('profile', nested =>
68
+ nested.field('bio').equals('Developer')
69
+ );
70
+ expect(nested.type).toBe('condition');
71
+ });
60
72
  });
61
- });
62
-
63
- describe('Nested structure creation', () => {
64
- test('should create nested callback structure', () => {
65
- const nested = nestedBuilder.nested('profile', nested =>
66
- LogicalOperator.Condition(nested.field('bio').equals('Developer'))
67
- );
68
-
69
- expect(nested.type).toBe('condition');
70
- });
71
- });
72
73
  });
73
74
 
74
75
  describe('NestedFieldConditionBuilder', () => {
75
- let fieldBuilder: NestedFieldConditionBuilder;
76
-
77
- beforeEach(() => {
78
- fieldBuilder = new NestedFieldConditionBuilder(['user', 'profile', 'details']);
79
- });
80
-
81
- describe('Path construction', () => {
82
- test('should construct correct field path', () => {
83
- const condition = fieldBuilder.equals('test');
84
- expect(condition.field).toBe('user.profile.details');
85
- });
86
-
87
- test('should work with single-level path', () => {
88
- const singleLevel = new NestedFieldConditionBuilder(['name']);
89
- const condition = singleLevel.equals('John');
90
- expect(condition.field).toBe('name');
91
- });
92
-
93
- test('should work with deep nesting', () => {
94
- const deepNesting = new NestedFieldConditionBuilder(['a', 'b', 'c', 'd', 'e']);
95
- const condition = deepNesting.contains('value');
96
- expect(condition.field).toBe('a.b.c.d.e');
97
- });
98
- });
99
-
100
- describe('Basic operators', () => {
101
- test('equals should create correct condition', () => {
102
- const condition = fieldBuilder.equals('value');
103
- expect(condition.field).toBe('user.profile.details');
104
- expect(condition.operator).toBe('is');
105
- expect(condition.value).toBe('value');
106
- });
107
-
108
- test('notEquals should create correct condition', () => {
109
- const condition = fieldBuilder.notEquals('value');
110
- expect(condition.operator).toBe('isNot');
111
- expect(condition.value).toBe('value');
112
- });
113
-
114
- test('comparison operators should work correctly', () => {
115
- expect(fieldBuilder.greaterThan(10).operator).toBe('greaterThan');
116
- expect(fieldBuilder.greaterThanOrEqual(10).operator).toBe('greaterThanOrEqual');
117
- expect(fieldBuilder.lessThan(10).operator).toBe('lessThan');
118
- expect(fieldBuilder.lessThanOrEqual(10).operator).toBe('lessThanOrEqual');
76
+ let fieldBuilder: NestedFieldConditionBuilder;
77
+
78
+ beforeEach(() => {
79
+ fieldBuilder = new NestedFieldConditionBuilder(['user', 'profile', 'details']);
80
+ });
81
+
82
+ describe('Path construction', () => {
83
+ test('should construct correct field path', () => {
84
+ expect(fieldBuilder.equals('test').condition?.field).toBe('user.profile.details');
85
+ });
86
+
87
+ test('should work with single-level path', () => {
88
+ const singleLevel = new NestedFieldConditionBuilder(['name']);
89
+ expect(singleLevel.equals('John').toComposable()).toEqual({ name: { is: 'John' } });
90
+ });
91
+
92
+ test('should work with deep nesting', () => {
93
+ const deepNesting = new NestedFieldConditionBuilder(['a', 'b', 'c', 'd', 'e']);
94
+ expect(deepNesting.contains('value').toComposable()).toEqual({
95
+ a: { b: { c: { d: { e: { includes: 'value' } } } } }
96
+ });
97
+ });
98
+ });
99
+
100
+ describe('Basic operators', () => {
101
+ test('equals', () => {
102
+ expect(fieldBuilder.equals('value').toComposable()).toEqual({
103
+ user: { profile: { details: { is: 'value' } } }
104
+ });
105
+ });
106
+
107
+ test('notEquals', () => {
108
+ expect(fieldBuilder.notEquals('value').toComposable()).toEqual({
109
+ user: { profile: { details: { isNot: 'value' } } }
110
+ });
111
+ });
112
+
113
+ test('comparison operators', () => {
114
+ expect(fieldBuilder.greaterThan(10).condition?.operator).toBe('greaterThan');
115
+ expect(fieldBuilder.greaterThanOrEqual(10).condition?.operator).toBe('greaterThanOrEqual');
116
+ expect(fieldBuilder.lessThan(10).condition?.operator).toBe('lessThan');
117
+ expect(fieldBuilder.lessThanOrEqual(10).condition?.operator).toBe('lessThanOrEqual');
118
+ });
119
+ });
120
+
121
+ describe('String operators', () => {
122
+ test('string operations', () => {
123
+ expect(fieldBuilder.contains('test').condition?.operator).toBe('includes');
124
+ expect(fieldBuilder.startsWith('pre').condition?.operator).toBe('startsWith');
125
+ expect(fieldBuilder.endsWith('suf').condition?.operator).toBe('endsWith');
126
+ expect(fieldBuilder.regExpMatches('.*').condition?.operator).toBe('regExpMatches');
127
+ expect(fieldBuilder.includesCaseInsensitive('TEST').condition?.operator).toBe('includesCaseInsensitive');
128
+ expect(fieldBuilder.startsWithCaseInsensitive('PRE').condition?.operator).toBe('startsWithCaseInsensitive');
129
+ expect(fieldBuilder.endsWithCaseInsensitive('SUF').condition?.operator).toBe('endsWithCaseInsensitive');
130
+ });
131
+ });
132
+
133
+ describe('Array operators', () => {
134
+ test('in and notIn', () => {
135
+ const inCondition = fieldBuilder.in([1, 2, 3]);
136
+ expect(inCondition.condition?.operator).toBe('in');
137
+ expect(inCondition.condition?.value).toEqual([1, 2, 3]);
138
+
139
+ const notInCondition = fieldBuilder.notIn(['a', 'b']);
140
+ expect(notInCondition.condition?.operator).toBe('notIn');
141
+ expect(notInCondition.condition?.value).toEqual(['a', 'b']);
142
+ });
143
+ });
144
+
145
+ describe('Existence operators', () => {
146
+ test('exists and notExists', () => {
147
+ expect(fieldBuilder.exists().toComposable()).toEqual({
148
+ user: { profile: { details: { exists: true } } }
149
+ });
150
+ expect(fieldBuilder.notExists().toComposable()).toEqual({
151
+ user: { profile: { details: { exists: false } } }
152
+ });
153
+ });
154
+
155
+ test('isNull and isNotNull', () => {
156
+ expect(fieldBuilder.isNull().toComposable()).toEqual({
157
+ user: { profile: { details: { isNull: true } } }
158
+ });
159
+ expect(fieldBuilder.isNotNull().toComposable()).toEqual({
160
+ user: { profile: { details: { isNull: false } } }
161
+ });
162
+ });
163
+ });
164
+
165
+ describe('Numeric operators', () => {
166
+ test('between uses betweenOp with from/to', () => {
167
+ const betweenCondition = fieldBuilder.between(10, 20);
168
+ expect(betweenCondition.condition?.operator).toBe('betweenOp');
169
+ expect(betweenCondition.condition?.value).toEqual({ from: 10, to: 20 });
170
+ });
171
+ });
172
+
173
+ describe('Misc operators', () => {
174
+ test('b64, inCountry, inDataset, cidr', () => {
175
+ expect(fieldBuilder.b64('dGVzdA==').condition?.operator).toBe('b64');
176
+ expect(fieldBuilder.inCountry('US').condition?.operator).toBe('inCountry');
177
+ expect(fieldBuilder.inDataset('malware_ips').condition?.operator).toBe('inDataset');
178
+ expect(fieldBuilder.cidr('192.168.1.0/24').condition?.operator).toBe('CIDR');
179
+ });
180
+
181
+ test('IP operators', () => {
182
+ expect(fieldBuilder.isLocalIp().condition?.operator).toBe('isLocalIp');
183
+ expect(fieldBuilder.isExternalIp().condition?.operator).toBe('isExternalIp');
184
+ });
185
+ });
186
+
187
+ describe('Boolean convenience', () => {
188
+ test('isTrue and isFalse', () => {
189
+ expect(fieldBuilder.isTrue().toComposable()).toEqual({
190
+ user: { profile: { details: { is: true } } }
191
+ });
192
+ expect(fieldBuilder.isFalse().toComposable()).toEqual({
193
+ user: { profile: { details: { is: false } } }
194
+ });
195
+ });
196
+ });
197
+
198
+ describe('Complex scenarios', () => {
199
+ test('should work with very deep nesting', () => {
200
+ const deepPath = ['level1', 'level2', 'level3', 'level4', 'level5', 'finalField'];
201
+ const deepBuilder = new NestedFieldConditionBuilder(deepPath);
202
+ const condition = deepBuilder.equals('deep_value');
203
+ expect(condition.condition?.field).toBe('level1.level2.level3.level4.level5.finalField');
204
+ expect(condition.condition?.value).toBe('deep_value');
205
+ });
206
+
207
+ test('should handle special characters in field names', () => {
208
+ const specialPath = ['user-profile', 'bio_text', 'data@field'];
209
+ const specialBuilder = new NestedFieldConditionBuilder(specialPath);
210
+ const condition = specialBuilder.contains('text');
211
+ expect(condition.condition?.field).toBe('user-profile.bio_text.data@field');
212
+ });
119
213
  });
120
- });
121
-
122
- describe('String operators', () => {
123
- test('string operations should work correctly', () => {
124
- expect(fieldBuilder.contains('test').operator).toBe('includes');
125
- expect(fieldBuilder.startsWith('pre').operator).toBe('startsWith');
126
- expect(fieldBuilder.endsWith('suf').operator).toBe('endsWith');
127
- expect(fieldBuilder.regExpMatches('.*').operator).toBe('regExpMatches');
128
- expect(fieldBuilder.includesCaseInsensitive('TEST').operator).toBe('includesCaseInsensitive');
129
- });
130
-
131
- test('wildcard operators should work correctly', () => {
132
- expect(fieldBuilder.wildcard('*.txt').operator).toBe('wildcard');
133
- expect(fieldBuilder.glob('**/*.js').operator).toBe('glob');
134
- });
135
- });
136
-
137
- describe('Array operators', () => {
138
- test('list operations should work correctly', () => {
139
- const inCondition = fieldBuilder.in([1, 2, 3]);
140
- expect(inCondition.operator).toBe('in');
141
- expect(inCondition.value).toEqual([1, 2, 3]);
142
-
143
- const notInCondition = fieldBuilder.notIn(['a', 'b']);
144
- expect(notInCondition.operator).toBe('notIn');
145
- expect(notInCondition.value).toEqual(['a', 'b']);
146
- });
147
-
148
- test('base operators should work correctly', () => {
149
- expect(fieldBuilder.equals('value').operator).toBe('is');
150
- expect(fieldBuilder.notEquals('value').operator).toBe('isNot');
151
- expect(fieldBuilder.isNull().operator).toBe('isNull');
152
- expect(fieldBuilder.isNotNull().operator).toBe('isNull');
153
- });
154
- });
155
-
156
- describe('Existence operators', () => {
157
- test('existence checks should work correctly', () => {
158
- expect(fieldBuilder.exists().operator).toBe('exists');
159
- expect(fieldBuilder.exists().value).toBe(true);
160
-
161
- expect(fieldBuilder.notExists().operator).toBe('exists');
162
- expect(fieldBuilder.notExists().value).toBe(false);
163
- });
164
-
165
- test('null checks should work correctly', () => {
166
- expect(fieldBuilder.isNull().operator).toBe('isNull');
167
- expect(fieldBuilder.isNull().value).toBe(true);
168
-
169
- expect(fieldBuilder.isNotNull().operator).toBe('isNull');
170
- expect(fieldBuilder.isNotNull().value).toBe(false);
171
- });
172
-
173
- test('empty checks should work correctly', () => {
174
- expect(fieldBuilder.isEmpty().operator).toBe('isEmpty');
175
- expect(fieldBuilder.isEmpty().value).toBe(true);
176
-
177
- expect(fieldBuilder.isNotEmpty().operator).toBe('isEmpty');
178
- expect(fieldBuilder.isNotEmpty().value).toBe(false);
179
- });
180
- });
181
-
182
- describe('Numeric operators', () => {
183
- test('number operations should work correctly', () => {
184
- const betweenCondition = fieldBuilder.between(10, 20);
185
- expect(betweenCondition.operator).toBe('betweenOp');
186
- expect(betweenCondition.value).toEqual({ from: 10, to: 20 });
187
-
188
- expect(fieldBuilder.greaterThan(100).operator).toBe('greaterThan');
189
- expect(fieldBuilder.lessThan(500).operator).toBe('lessThan');
190
- expect(fieldBuilder.greaterThanOrEqual(100).operator).toBe('greaterThanOrEqual');
191
- expect(fieldBuilder.lessThanOrEqual(500).operator).toBe('lessThanOrEqual');
192
- });
193
- });
194
-
195
- describe('Misc operators', () => {
196
- test('misc operators should work correctly', () => {
197
- expect(fieldBuilder.b64('dGVzdA==').operator).toBe('b64');
198
- expect(fieldBuilder.inCountry('US').operator).toBe('inCountry');
199
- expect(fieldBuilder.inDataset('malware_ips').operator).toBe('inDataset');
200
- expect(fieldBuilder.cidr('192.168.1.0/24').operator).toBe('CIDR');
201
- });
202
- });
203
-
204
- describe('Boolean operators', () => {
205
- test('boolean checks should work correctly', () => {
206
- const trueCondition = fieldBuilder.isTrue();
207
- expect(trueCondition.operator).toBe('is');
208
- expect(trueCondition.value).toBe(true);
209
-
210
- const falseCondition = fieldBuilder.isFalse();
211
- expect(falseCondition.operator).toBe('is');
212
- expect(falseCondition.value).toBe(false);
213
- });
214
- });
215
-
216
- describe('Type checking operators', () => {
217
- test('type validation operators should work correctly', () => {
218
- expect(fieldBuilder.isString().operator).toBe('isString');
219
- expect(fieldBuilder.isNumber().operator).toBe('isNumber');
220
- expect(fieldBuilder.isBoolean().operator).toBe('isBoolean');
221
- expect(fieldBuilder.isArray().operator).toBe('isArray');
222
- expect(fieldBuilder.isObject().operator).toBe('isObject');
223
- });
224
- });
225
-
226
- describe('String operators', () => {
227
- test('string operators should work correctly', () => {
228
- expect(fieldBuilder.startsWith('prefix').operator).toBe('startsWith');
229
- expect(fieldBuilder.endsWith('suffix').operator).toBe('endsWith');
230
- expect(fieldBuilder.contains('substring').operator).toBe('includes');
231
- expect(fieldBuilder.regExpMatches('^test.*').operator).toBe('regExpMatches');
232
- expect(fieldBuilder.includesCaseInsensitive('Test').operator).toBe('includesCaseInsensitive');
233
- });
234
- });
235
-
236
- describe('IP address operators', () => {
237
- test('IP address operations should work correctly', () => {
238
- expect(fieldBuilder.isLocalIp().operator).toBe('isLocalIp');
239
- expect(fieldBuilder.isExternalIp().operator).toBe('isExternalIp');
240
- expect(fieldBuilder.inCountry('US').operator).toBe('inCountry');
241
- expect(fieldBuilder.cidr('192.168.1.0/24').operator).toBe('CIDR');
242
- expect(fieldBuilder.b64('dGVzdA==').operator).toBe('b64');
243
- expect(fieldBuilder.inDataset('malware_ips').operator).toBe('inDataset');
244
- });
245
- });
246
-
247
- describe('Number operators', () => {
248
- test('number operations should work correctly', () => {
249
- expect(fieldBuilder.greaterThan(100).operator).toBe('greaterThan');
250
- expect(fieldBuilder.lessThan(500).operator).toBe('lessThan');
251
- expect(fieldBuilder.greaterThanOrEqual(100).operator).toBe('greaterThanOrEqual');
252
- expect(fieldBuilder.lessThanOrEqual(500).operator).toBe('lessThanOrEqual');
253
- expect(fieldBuilder.between(100, 500).operator).toBe('betweenOp');
254
- });
255
- });
256
-
257
- describe('Complex scenarios', () => {
258
- test('should work with very deep nesting', () => {
259
- const deepPath = ['level1', 'level2', 'level3', 'level4', 'level5', 'finalField'];
260
- const deepBuilder = new NestedFieldConditionBuilder(deepPath);
261
- const condition = deepBuilder.equals('deep_value');
262
-
263
- expect(condition.field).toBe('level1.level2.level3.level4.level5.finalField');
264
- expect(condition.value).toBe('deep_value');
265
- });
266
-
267
- test('should handle special characters in field names', () => {
268
- const specialPath = ['user-profile', 'bio_text', 'data@field'];
269
- const specialBuilder = new NestedFieldConditionBuilder(specialPath);
270
- const condition = specialBuilder.contains('text');
271
-
272
- expect(condition.field).toBe('user-profile.bio_text.data@field');
273
- });
274
-
275
- test('should work with all operator types in nested context', () => {
276
- const nestedBuilder = new NestedConditionBuilder('order');
277
- const itemsBuilder = nestedBuilder.field('items');
278
-
279
- // Test that we can chain multiple field levels
280
- const priceCondition = itemsBuilder.field('price').greaterThan(100);
281
- expect(priceCondition.field).toBe('order.items.price');
282
-
283
- const categoryCondition = itemsBuilder.field('category').equals('electronics');
284
- expect(categoryCondition.field).toBe('order.items.category');
285
-
286
- const stockCondition = itemsBuilder.field('stock').exists();
287
- expect(stockCondition.field).toBe('order.items.stock');
288
- });
289
- });
290
214
  });
291
215
 
292
216
  describe('Integration with LogicalOperator', () => {
293
- test('should work correctly with LogicalOperator.Condition', () => {
294
- const nestedBuilder = new NestedConditionBuilder('user');
295
- const condition = new NestedFieldConditionBuilder(['user', 'profile', 'name']).equals('John');
296
- const logicalOp = LogicalOperator.Condition(condition);
297
-
298
- expect(logicalOp.type).toBe('condition');
299
- expect(logicalOp.condition?.field).toBe('user.profile.name');
300
- });
301
-
302
- test('should work in complex logical structures', () => {
303
- const nestedBuilder = new NestedConditionBuilder('user');
304
-
305
- const complexLogic = LogicalOperator.And([
306
- LogicalOperator.Condition(new NestedFieldConditionBuilder(['user', 'profile', 'name']).equals('John')),
307
- LogicalOperator.Or([
308
- LogicalOperator.Condition(nestedBuilder.field('status').equals('active')),
309
- LogicalOperator.Condition(nestedBuilder.field('status').equals('pending'))
310
- ]),
311
- LogicalOperator.Not([
312
- LogicalOperator.Condition(new NestedFieldConditionBuilder(['user', 'flags', 'deleted']).isTrue())
313
- ])
314
- ]);
315
-
316
- expect(complexLogic.type).toBe('and');
317
- expect(complexLogic.conditions).toHaveLength(3);
318
- expect(complexLogic.conditions[1].type).toBe('or');
319
- expect(complexLogic.conditions[2].type).toBe('not');
320
- });
321
- });
217
+ test('should have correct type and condition from NestedFieldConditionBuilder', () => {
218
+ const condition = new NestedFieldConditionBuilder(['user', 'profile', 'name']).equals('John');
219
+ expect(condition.type).toBe('condition');
220
+ expect(condition.condition?.field).toBe('user.profile.name');
221
+ });
222
+
223
+ test('should work in complex logical structures', () => {
224
+ const nestedBuilder = new NestedConditionBuilder('user');
225
+ const complexLogic = LogicalOperator.And([
226
+ new NestedFieldConditionBuilder(['user', 'profile', 'name']).equals('John'),
227
+ LogicalOperator.Or([
228
+ nestedBuilder.field('status').equals('active'),
229
+ nestedBuilder.field('status').equals('pending')
230
+ ]),
231
+ LogicalOperator.Not([
232
+ new NestedFieldConditionBuilder(['user', 'flags', 'deleted']).isTrue()
233
+ ])
234
+ ]);
235
+
236
+ expect(complexLogic.type).toBe('and');
237
+ expect(complexLogic.conditions).toHaveLength(3);
238
+ expect(complexLogic.conditions[1].type).toBe('or');
239
+ expect(complexLogic.conditions[2].type).toBe('not');
240
+ });
241
+ });
@@ -78,8 +78,8 @@ describe('QueryBuilder', () => {
78
78
  .collection('users')
79
79
  .find(builder =>
80
80
  LogicalOperator.And([
81
- LogicalOperator.Condition(new FieldConditionBuilder('name').equals('John')),
82
- LogicalOperator.Condition(new FieldConditionBuilder('age').greaterThan(25))
81
+ new FieldConditionBuilder('name').equals('John'),
82
+ new FieldConditionBuilder('age').greaterThan(25)
83
83
  ])
84
84
  )
85
85
  .buildRawQuery();
@@ -97,8 +97,8 @@ describe('QueryBuilder', () => {
97
97
  .collection('users')
98
98
  .find(builder =>
99
99
  LogicalOperator.Or([
100
- LogicalOperator.Condition(new FieldConditionBuilder('role').equals('admin')),
101
- LogicalOperator.Condition(new FieldConditionBuilder('role').equals('moderator'))
100
+ new FieldConditionBuilder('role').equals('admin'),
101
+ new FieldConditionBuilder('role').equals('moderator')
102
102
  ])
103
103
  )
104
104
  .buildRawQuery();
@@ -116,7 +116,7 @@ describe('QueryBuilder', () => {
116
116
  .collection('users')
117
117
  .find(builder =>
118
118
  LogicalOperator.Not([
119
- LogicalOperator.Condition(new FieldConditionBuilder('status').equals('banned'))
119
+ new FieldConditionBuilder('status').equals('banned')
120
120
  ])
121
121
  )
122
122
  .buildRawQuery();