@onchaindb/sdk 0.4.0 → 0.4.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 (98) hide show
  1. package/.DS_Store +0 -0
  2. package/.claude/settings.local.json +8 -0
  3. package/.gitignore +5 -0
  4. package/.idea/.gitignore +5 -0
  5. package/.idea/compiler.xml +6 -0
  6. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  7. package/.idea/jsLinters/eslint.xml +6 -0
  8. package/.idea/modules.xml +8 -0
  9. package/.idea/prettier.xml +7 -0
  10. package/.idea/sdk.iml +12 -0
  11. package/.idea/vcs.xml +6 -0
  12. package/.idea/workspace.xml +257 -0
  13. package/dist/client.d.ts.map +1 -1
  14. package/dist/client.js +11 -3
  15. package/dist/client.js.map +1 -1
  16. package/dist/database.d.ts +0 -20
  17. package/dist/database.d.ts.map +1 -1
  18. package/dist/database.js +0 -40
  19. package/dist/database.js.map +1 -1
  20. package/dist/query-sdk/tests/setup.d.ts +16 -0
  21. package/dist/query-sdk/tests/setup.d.ts.map +1 -0
  22. package/dist/query-sdk/tests/setup.js +49 -0
  23. package/dist/query-sdk/tests/setup.js.map +1 -0
  24. package/examples/basic-usage.ts +136 -0
  25. package/examples/blob-upload-example.ts +140 -0
  26. package/examples/collection-schema-example.ts +304 -0
  27. package/examples/server-side-joins.ts +201 -0
  28. package/examples/tweet-self-joins-example.ts +352 -0
  29. package/package-lock.json +3823 -0
  30. package/package.json +1 -1
  31. package/skills.md +1096 -0
  32. package/src/.env +1 -0
  33. package/src/batch.d.ts +121 -0
  34. package/src/batch.js +205 -0
  35. package/src/batch.ts +257 -0
  36. package/src/client.ts +1856 -0
  37. package/src/database.d.ts +268 -0
  38. package/src/database.js +294 -0
  39. package/src/database.ts +695 -0
  40. package/src/index.d.ts +160 -0
  41. package/src/index.js +186 -0
  42. package/src/index.ts +253 -0
  43. package/src/query-sdk/ConditionBuilder.ts +103 -0
  44. package/src/query-sdk/FieldConditionBuilder.ts +2 -0
  45. package/src/query-sdk/NestedBuilders.ts +186 -0
  46. package/src/query-sdk/OnChainDB.ts +294 -0
  47. package/src/query-sdk/QueryBuilder.ts +1191 -0
  48. package/src/query-sdk/QueryResult.ts +375 -0
  49. package/src/query-sdk/README.md +866 -0
  50. package/src/query-sdk/SelectionBuilder.ts +94 -0
  51. package/src/query-sdk/adapters/HttpClientAdapter.ts +249 -0
  52. package/src/query-sdk/dist/ConditionBuilder.d.ts +22 -0
  53. package/src/query-sdk/dist/ConditionBuilder.js +90 -0
  54. package/src/query-sdk/dist/FieldConditionBuilder.d.ts +1 -0
  55. package/src/query-sdk/dist/FieldConditionBuilder.js +6 -0
  56. package/src/query-sdk/dist/NestedBuilders.d.ts +43 -0
  57. package/src/query-sdk/dist/NestedBuilders.js +144 -0
  58. package/src/query-sdk/dist/OnChainDB.d.ts +19 -0
  59. package/src/query-sdk/dist/OnChainDB.js +123 -0
  60. package/src/query-sdk/dist/QueryBuilder.d.ts +70 -0
  61. package/src/query-sdk/dist/QueryBuilder.js +295 -0
  62. package/src/query-sdk/dist/QueryResult.d.ts +52 -0
  63. package/src/query-sdk/dist/QueryResult.js +293 -0
  64. package/src/query-sdk/dist/SelectionBuilder.d.ts +20 -0
  65. package/src/query-sdk/dist/SelectionBuilder.js +80 -0
  66. package/src/query-sdk/dist/adapters/HttpClientAdapter.d.ts +27 -0
  67. package/src/query-sdk/dist/adapters/HttpClientAdapter.js +170 -0
  68. package/src/query-sdk/dist/index.d.ts +36 -0
  69. package/src/query-sdk/dist/index.js +27 -0
  70. package/src/query-sdk/dist/operators.d.ts +56 -0
  71. package/src/query-sdk/dist/operators.js +289 -0
  72. package/src/query-sdk/dist/tests/setup.d.ts +15 -0
  73. package/src/query-sdk/dist/tests/setup.js +46 -0
  74. package/src/query-sdk/index.ts +59 -0
  75. package/src/query-sdk/jest.config.js +25 -0
  76. package/src/query-sdk/operators.ts +335 -0
  77. package/src/query-sdk/package.json +46 -0
  78. package/src/query-sdk/tests/FieldConditionBuilder.test.ts +84 -0
  79. package/src/query-sdk/tests/LogicalOperator.test.ts +85 -0
  80. package/src/query-sdk/tests/NestedBuilders.test.ts +321 -0
  81. package/src/query-sdk/tests/QueryBuilder.test.ts +348 -0
  82. package/src/query-sdk/tests/QueryResult.test.ts +464 -0
  83. package/src/query-sdk/tests/aggregations.test.ts +653 -0
  84. package/src/query-sdk/tests/comprehensive.test.ts +279 -0
  85. package/src/query-sdk/tests/integration.test.ts +608 -0
  86. package/src/query-sdk/tests/operators.test.ts +327 -0
  87. package/src/query-sdk/tests/setup.ts +59 -0
  88. package/src/query-sdk/tests/unit.test.ts +794 -0
  89. package/src/query-sdk/tsconfig.json +26 -0
  90. package/src/query-sdk/yarn.lock +3092 -0
  91. package/src/types.d.ts +131 -0
  92. package/src/types.js +46 -0
  93. package/src/types.ts +534 -0
  94. package/src/x402/index.ts +12 -0
  95. package/src/x402/types.ts +250 -0
  96. package/src/x402/utils.ts +332 -0
  97. package/tsconfig.json +20 -0
  98. package/yarn.lock +2309 -0
@@ -0,0 +1,279 @@
1
+ import { QueryBuilder, FieldConditionBuilder, LogicalOperator, createQueryResult } from '../index';
2
+ import { MockHttpClient, createMockResponse } from './setup';
3
+
4
+ describe('Comprehensive SDK Integration Tests', () => {
5
+ let mockClient: MockHttpClient;
6
+ let queryBuilder: QueryBuilder;
7
+
8
+ beforeEach(() => {
9
+ mockClient = new MockHttpClient();
10
+ queryBuilder = new QueryBuilder(mockClient, 'http://localhost:3000', 'testApp');
11
+ });
12
+
13
+ afterEach(() => {
14
+ mockClient.clear();
15
+ });
16
+
17
+ describe('Complete query building workflow', () => {
18
+ test('should build complex nested query with dot notation', () => {
19
+ const rawQuery = queryBuilder
20
+ .collection('users')
21
+ .whereField('user.profile.bio').contains('Developer')
22
+ .limit(10)
23
+ .selectFields(['id', 'name'])
24
+ .buildRawQuery();
25
+
26
+ expect(rawQuery.find).toEqual({
27
+ user: {
28
+ profile: {
29
+ bio: {
30
+ includes: 'Developer'
31
+ }
32
+ }
33
+ }
34
+ });
35
+
36
+ expect(rawQuery.limit).toBe(10);
37
+ expect(rawQuery.select).toEqual({ fields: ['id', 'name'] });
38
+ });
39
+
40
+ test('should handle deep nesting scenarios', () => {
41
+ const deepCondition = new FieldConditionBuilder('user.profile.settings.preferences.theme').equals('dark');
42
+ const logicalOp = LogicalOperator.Condition(deepCondition);
43
+ const composable = logicalOp.toComposable();
44
+
45
+ const expected = {
46
+ user: {
47
+ profile: {
48
+ settings: {
49
+ preferences: {
50
+ theme: {
51
+ is: 'dark'
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ };
58
+
59
+ expect(composable).toEqual(expected);
60
+ });
61
+
62
+ test('should execute full workflow with mock client', async () => {
63
+ const mockData = [
64
+ { id: 1, name: 'John Doe', user: { profile: { bio: 'Developer' } } },
65
+ { id: 2, name: 'Jane Smith', user: { profile: { bio: 'Designer' } } }
66
+ ];
67
+
68
+ mockClient.setResponse('/list', createMockResponse(mockData));
69
+
70
+ const response = await queryBuilder
71
+ .collection('users')
72
+ .whereField('user.profile.bio').contains('Developer')
73
+ .limit(10)
74
+ .selectFields(['id', 'name'])
75
+ .execute();
76
+
77
+ expect(response.records).toEqual(mockData);
78
+ expect(response.total).toBe(2);
79
+ });
80
+ });
81
+
82
+ describe('QueryResult advanced operations', () => {
83
+ test('should perform complex join operations', () => {
84
+ const users = createQueryResult([
85
+ { id: 1, name: 'John', departmentId: 1 },
86
+ { id: 2, name: 'Jane', departmentId: 2 }
87
+ ]);
88
+
89
+ const departments = createQueryResult([
90
+ { id: 1, name: 'Engineering' },
91
+ { id: 2, name: 'Design' }
92
+ ]);
93
+
94
+ const joined = users.innerJoin(departments, 'departmentId', 'id');
95
+ expect(joined.length).toBe(2);
96
+ expect(joined[0].name).toBe('Engineering'); // Department name merged
97
+ expect(joined[1].name).toBe('Design');
98
+ });
99
+
100
+ test('should export to CSV with proper formatting', () => {
101
+ const users = createQueryResult([
102
+ { id: 1, name: 'John', age: 30, score: 95.5 },
103
+ { id: 2, name: 'Jane', age: 25, score: 87.2 },
104
+ { id: 3, name: 'Bob', age: 35, score: 92.8 }
105
+ ]);
106
+
107
+ const csv = users.toCsv();
108
+ const lines = csv.split('\n');
109
+
110
+ expect(lines.length).toBe(4); // header + 3 data rows
111
+ expect(lines[0]).toContain('id');
112
+ expect(lines[0]).toContain('name');
113
+ expect(lines[0]).toContain('age');
114
+ expect(lines[0]).toContain('score');
115
+ });
116
+
117
+ test('should provide comprehensive numeric summaries', () => {
118
+ const testData = [
119
+ { id: 1, name: 'John', age: 30, score: 95.5 },
120
+ { id: 2, name: 'Jane', age: 25, score: 87.2 },
121
+ { id: 3, name: 'Bob', age: 35, score: 92.8 }
122
+ ];
123
+
124
+ const result = createQueryResult(testData);
125
+ const scoreSummary = result.summarizeNumeric('score');
126
+
127
+ expect(scoreSummary).not.toBeNull();
128
+ expect(scoreSummary!.count).toBe(3);
129
+ expect(scoreSummary!.mean).toBeCloseTo((95.5 + 87.2 + 92.8) / 3, 2);
130
+ expect(scoreSummary!.min).toBe(87.2);
131
+ expect(scoreSummary!.max).toBe(95.5);
132
+ });
133
+
134
+ test('should handle sorting and filtering', () => {
135
+ const testData = [
136
+ { id: 1, name: 'John', age: 30 },
137
+ { id: 2, name: 'Jane', age: 25 },
138
+ { id: 3, name: 'Bob', age: 35 }
139
+ ];
140
+
141
+ const result = createQueryResult(testData);
142
+
143
+ const sortedByAge = result.sortBy('age');
144
+ expect(sortedByAge[0].age).toBe(25);
145
+ expect(sortedByAge[2].age).toBe(35);
146
+
147
+ const filtered = result.filter(item => item.age > 30);
148
+ expect(filtered.length).toBe(1);
149
+ expect(filtered[0].name).toBe('Bob');
150
+
151
+ const grouped = result.groupBy('age');
152
+ expect(Object.keys(grouped).length).toBe(3);
153
+ });
154
+ });
155
+
156
+ describe('Error handling and validation', () => {
157
+ test('should handle empty QueryResult operations gracefully', () => {
158
+ const emptyResult = createQueryResult([]);
159
+
160
+ expect(emptyResult.isEmpty()).toBe(true);
161
+ expect(emptyResult.first()).toBeUndefined();
162
+ expect(emptyResult.len()).toBe(0);
163
+ expect(emptyResult.summarizeNumeric('field')).toBeNull();
164
+ });
165
+
166
+ test('should validate QueryBuilder state', () => {
167
+ const emptyBuilder = new QueryBuilder();
168
+ expect(emptyBuilder.isValid()).toBe(false);
169
+
170
+ const builderWithCondition = new QueryBuilder()
171
+ .whereField('name').equals('test');
172
+ expect(builderWithCondition.isValid()).toBe(true);
173
+ });
174
+
175
+ test('should handle invalid field references', () => {
176
+ expect(() => {
177
+ const condition = new FieldConditionBuilder('').equals('test');
178
+ LogicalOperator.Condition(condition).toComposable();
179
+ }).not.toThrow();
180
+ });
181
+ });
182
+
183
+ describe('All operators comprehensive coverage', () => {
184
+ test('should support all field condition operators', () => {
185
+ const builder = new FieldConditionBuilder('test_field');
186
+
187
+ // Only test operators that actually exist in the Rust implementation
188
+ const operators = [
189
+ 'equals', 'notEquals', 'greaterThan', 'lessThan', 'greaterThanOrEqual', 'lessThanOrEqual',
190
+ 'contains', 'startsWith', 'endsWith', 'in', 'notIn', 'exists', 'notExists',
191
+ 'isNull', 'isNotNull', 'regExpMatches', 'includesCaseInsensitive',
192
+ 'startsWithCaseInsensitive', 'endsWithCaseInsensitive', 'between',
193
+ 'isLocalIp', 'isExternalIp', 'b64', 'inDataset', 'inCountry', 'cidr',
194
+ 'isTrue', 'isFalse'
195
+ ];
196
+
197
+ operators.forEach(op => {
198
+ expect(typeof (builder as any)[op]).toBe('function');
199
+ });
200
+ });
201
+
202
+ test('should create correct conditions for advanced operators', () => {
203
+ const builder = new FieldConditionBuilder('test_field');
204
+
205
+ // String operators
206
+ const regexCondition = builder.regExpMatches('^test.*');
207
+ expect(regexCondition.operator).toBe('regExpMatches');
208
+
209
+ const caseInsensitiveCondition = builder.includesCaseInsensitive('Test');
210
+ expect(caseInsensitiveCondition.operator).toBe('includesCaseInsensitive');
211
+
212
+ // IP operators
213
+ const ipBuilder = new FieldConditionBuilder('ip_address');
214
+ const ipLocalCondition = ipBuilder.isLocalIp();
215
+ expect(ipLocalCondition.operator).toBe('isLocalIp');
216
+
217
+ const ipExternalCondition = ipBuilder.isExternalIp();
218
+ expect(ipExternalCondition.operator).toBe('isExternalIp');
219
+
220
+ // Misc operators
221
+ const b64Condition = builder.b64('dGVzdA==');
222
+ expect(b64Condition.operator).toBe('b64');
223
+
224
+ const countryCondition = builder.inCountry('US');
225
+ expect(countryCondition.operator).toBe('inCountry');
226
+
227
+ const cidrCondition = builder.cidr('192.168.1.0/24');
228
+ expect(cidrCondition.operator).toBe('CIDR');
229
+
230
+ const datasetCondition = builder.inDataset('malware_ips');
231
+ expect(datasetCondition.operator).toBe('inDataset');
232
+
233
+ const betweenCondition = builder.between(5, 15);
234
+ expect(betweenCondition.operator).toBe('betweenOp');
235
+ });
236
+ });
237
+
238
+ describe('Performance and memory scenarios', () => {
239
+ test('should handle large datasets efficiently', () => {
240
+ const largeDataset = Array.from({ length: 1000 }, (_, i) => ({
241
+ id: i,
242
+ name: `User${i}`,
243
+ value: Math.random() * 100
244
+ }));
245
+
246
+ const result = createQueryResult(largeDataset);
247
+ expect(result.len()).toBe(1000);
248
+
249
+ const filtered = result.filter(item => item.value > 50);
250
+ expect(filtered.length).toBeGreaterThan(0);
251
+
252
+ const summary = result.summarizeNumeric('value');
253
+ expect(summary).not.toBeNull();
254
+ expect(summary!.count).toBe(1000);
255
+ });
256
+
257
+ test('should handle complex nested structures', () => {
258
+ const complexData = Array.from({ length: 100 }, (_, i) => ({
259
+ id: i,
260
+ user: {
261
+ profile: {
262
+ details: {
263
+ settings: {
264
+ preferences: {
265
+ theme: i % 2 === 0 ? 'dark' : 'light'
266
+ }
267
+ }
268
+ }
269
+ }
270
+ }
271
+ }));
272
+
273
+ const result = createQueryResult(complexData);
274
+ const themes = result.pluck('user.profile.details.settings.preferences.theme');
275
+ expect(themes.filter(theme => theme === 'dark')).toHaveLength(50);
276
+ expect(themes.filter(theme => theme === 'light')).toHaveLength(50);
277
+ });
278
+ });
279
+ });