@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,335 @@
1
+ import { BetweenValue, DateRange, Val } from './index';
2
+
3
+ // Condition represents a single field condition
4
+ export interface Condition {
5
+ field: string;
6
+ operator: string;
7
+ value: Val | BetweenValue | DateRange;
8
+ }
9
+
10
+ // Helper function to convert dot notation paths to nested structures
11
+ export function createNestedQuery(fieldPath: string, operator: string, value: Val | BetweenValue | DateRange): any {
12
+ if (!fieldPath.includes('.')) {
13
+ return {
14
+ [fieldPath]: {
15
+ [operator]: value
16
+ }
17
+ };
18
+ }
19
+
20
+ const pathParts = fieldPath.split('.');
21
+ let result: any = {
22
+ [operator]: value
23
+ };
24
+
25
+ // Build nested structure from inside out
26
+ for (let i = pathParts.length - 1; i >= 0; i--) {
27
+ const part = pathParts[i];
28
+ if (i === pathParts.length - 1) {
29
+ result = {
30
+ [part]: result
31
+ };
32
+ } else {
33
+ result = {
34
+ [part]: result
35
+ };
36
+ }
37
+ }
38
+
39
+ return result;
40
+ }
41
+
42
+ // Logical operators for combining conditions
43
+ export enum LogicalOperatorType {
44
+ AND = 'and',
45
+ OR = 'or',
46
+ NOT = 'not',
47
+ CONDITION = 'condition'
48
+ }
49
+
50
+ export class LogicalOperator {
51
+ constructor(
52
+ public type: LogicalOperatorType,
53
+ public conditions: LogicalOperator[] = [],
54
+ public condition?: Condition
55
+ ) {
56
+ }
57
+
58
+ static And(conditions: LogicalOperator[]): LogicalOperator {
59
+ return new LogicalOperator(LogicalOperatorType.AND, conditions);
60
+ }
61
+
62
+ static Or(conditions: LogicalOperator[]): LogicalOperator {
63
+ return new LogicalOperator(LogicalOperatorType.OR, conditions);
64
+ }
65
+
66
+ static Not(conditions: LogicalOperator[]): LogicalOperator {
67
+ return new LogicalOperator(LogicalOperatorType.NOT, conditions);
68
+ }
69
+
70
+ static Condition(condition: Condition): LogicalOperator {
71
+ return new LogicalOperator(LogicalOperatorType.CONDITION, [], condition);
72
+ }
73
+
74
+ // Convert to composable query structure for HTTP requests
75
+ toComposable(): any {
76
+ switch (this.type) {
77
+ case LogicalOperatorType.AND:
78
+ return {
79
+ [LogicalOperatorType.AND]: this.conditions.map(c => c.toComposable())
80
+ };
81
+ case LogicalOperatorType.OR:
82
+ return {
83
+ [LogicalOperatorType.OR]: this.conditions.map(c => c.toComposable())
84
+ };
85
+ case LogicalOperatorType.NOT:
86
+ return {
87
+ [LogicalOperatorType.NOT]: this.conditions.map(c => c.toComposable())
88
+ };
89
+ case LogicalOperatorType.CONDITION:
90
+ if (!this.condition) throw new Error('Condition is required for CONDITION type');
91
+ // Use dot notation helper to create nested structures
92
+ return createNestedQuery(this.condition.field, this.condition.operator, this.condition.value);
93
+ default:
94
+ throw new Error(`Unknown logical operator type: ${this.type}`);
95
+ }
96
+ }
97
+ }
98
+
99
+ // Field condition builder for creating individual field conditions
100
+ // Only includes operators that actually exist in the Rust implementation
101
+ export class FieldConditionBuilder {
102
+ constructor(private fieldName: string) {
103
+ }
104
+
105
+ // ===== BASE OPERATORS (BaseOperator) =====
106
+
107
+ equals(value: Val): Condition {
108
+ return {
109
+ field: this.fieldName,
110
+ operator: 'is',
111
+ value
112
+ };
113
+ }
114
+
115
+ notEquals(value: Val): Condition {
116
+ return {
117
+ field: this.fieldName,
118
+ operator: 'isNot',
119
+ value
120
+ };
121
+ }
122
+
123
+ in(values: Val[]): Condition {
124
+ return {
125
+ field: this.fieldName,
126
+ operator: 'in',
127
+ value: values as any
128
+ };
129
+ }
130
+
131
+ notIn(values: Val[]): Condition {
132
+ return {
133
+ field: this.fieldName,
134
+ operator: 'notIn',
135
+ value: values as any
136
+ };
137
+ }
138
+
139
+ isNull(): Condition {
140
+ return {
141
+ field: this.fieldName,
142
+ operator: 'isNull',
143
+ value: true
144
+ };
145
+ }
146
+
147
+ isNotNull(): Condition {
148
+ return {
149
+ field: this.fieldName,
150
+ operator: 'isNull',
151
+ value: false
152
+ };
153
+ }
154
+
155
+ exists(): Condition {
156
+ return {
157
+ field: this.fieldName,
158
+ operator: 'exists',
159
+ value: true
160
+ };
161
+ }
162
+
163
+ notExists(): Condition {
164
+ return {
165
+ field: this.fieldName,
166
+ operator: 'exists',
167
+ value: false
168
+ };
169
+ }
170
+
171
+ // ===== STRING OPERATORS (StringOperator) =====
172
+
173
+ startsWith(value: string): Condition {
174
+ return {
175
+ field: this.fieldName,
176
+ operator: 'startsWith',
177
+ value
178
+ };
179
+ }
180
+
181
+ endsWith(value: string): Condition {
182
+ return {
183
+ field: this.fieldName,
184
+ operator: 'endsWith',
185
+ value
186
+ };
187
+ }
188
+
189
+ contains(value: string): Condition {
190
+ return {
191
+ field: this.fieldName,
192
+ operator: 'includes',
193
+ value
194
+ };
195
+ }
196
+
197
+ regExpMatches(pattern: string): Condition {
198
+ return {
199
+ field: this.fieldName,
200
+ operator: 'regExpMatches',
201
+ value: pattern
202
+ };
203
+ }
204
+
205
+ includesCaseInsensitive(value: string): Condition {
206
+ return {
207
+ field: this.fieldName,
208
+ operator: 'includesCaseInsensitive',
209
+ value
210
+ };
211
+ }
212
+
213
+ startsWithCaseInsensitive(value: string): Condition {
214
+ return {
215
+ field: this.fieldName,
216
+ operator: 'startsWithCaseInsensitive',
217
+ value
218
+ };
219
+ }
220
+
221
+ endsWithCaseInsensitive(value: string): Condition {
222
+ return {
223
+ field: this.fieldName,
224
+ operator: 'endsWithCaseInsensitive',
225
+ value
226
+ };
227
+ }
228
+
229
+ // ===== NUMBER OPERATORS (NumberOperator) =====
230
+
231
+ greaterThan(value: Val): Condition {
232
+ return {
233
+ field: this.fieldName,
234
+ operator: 'greaterThan',
235
+ value
236
+ };
237
+ }
238
+
239
+ lessThan(value: Val): Condition {
240
+ return {
241
+ field: this.fieldName,
242
+ operator: 'lessThan',
243
+ value
244
+ };
245
+ }
246
+
247
+ greaterThanOrEqual(value: Val): Condition {
248
+ return {
249
+ field: this.fieldName,
250
+ operator: 'greaterThanOrEqual',
251
+ value
252
+ };
253
+ }
254
+
255
+ lessThanOrEqual(value: Val): Condition {
256
+ return {
257
+ field: this.fieldName,
258
+ operator: 'lessThanOrEqual',
259
+ value
260
+ };
261
+ }
262
+
263
+ // ===== IP OPERATORS (IpOperator) =====
264
+
265
+ isLocalIp(): Condition {
266
+ return {
267
+ field: this.fieldName,
268
+ operator: 'isLocalIp',
269
+ value: true
270
+ };
271
+ }
272
+
273
+ isExternalIp(): Condition {
274
+ return {
275
+ field: this.fieldName,
276
+ operator: 'isExternalIp',
277
+ value: true
278
+ };
279
+ }
280
+
281
+ // ===== MISC OPERATORS (MiscOperator) =====
282
+
283
+ b64(value: string): Condition {
284
+ return {
285
+ field: this.fieldName,
286
+ operator: 'b64',
287
+ value
288
+ };
289
+ }
290
+
291
+ inDataset(dataset: string): Condition {
292
+ return {
293
+ field: this.fieldName,
294
+ operator: 'inDataset',
295
+ value: dataset
296
+ };
297
+ }
298
+
299
+ inCountry(countryCode: string): Condition {
300
+ return {
301
+ field: this.fieldName,
302
+ operator: 'inCountry',
303
+ value: countryCode
304
+ };
305
+ }
306
+
307
+ cidr(cidr: string): Condition {
308
+ return {
309
+ field: this.fieldName,
310
+ operator: 'CIDR',
311
+ value: cidr
312
+ };
313
+ }
314
+
315
+ // ===== BETWEEN OPERATOR =====
316
+
317
+ between(min: Val, max: Val): Condition {
318
+ return {
319
+ field: this.fieldName,
320
+ operator: 'betweenOp',
321
+ value: { from: min, to: max } as any
322
+ };
323
+ }
324
+
325
+ // ===== CONVENIENCE METHODS =====
326
+
327
+ // Boolean checks (using base operators)
328
+ isTrue(): Condition {
329
+ return this.equals(true);
330
+ }
331
+
332
+ isFalse(): Condition {
333
+ return this.equals(false);
334
+ }
335
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@scepter/typescript-sdk",
3
+ "version": "1.0.0",
4
+ "description": "TypeScript SDK for Scepter JSON query engine",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "scripts": {
8
+ "test": "jest",
9
+ "test:watch": "jest --watch",
10
+ "test:coverage": "jest --coverage",
11
+ "build": "tsc",
12
+ "lint": "eslint src/**/*.ts",
13
+ "prepare": "npm run build"
14
+ },
15
+ "keywords": [
16
+ "query",
17
+ "json",
18
+ "database",
19
+ "typescript",
20
+ "sdk"
21
+ ],
22
+ "author": "Scepter Team",
23
+ "license": "MIT",
24
+ "devDependencies": {
25
+ "@types/jest": "^30.0.0",
26
+ "@types/node": "^20.8.0",
27
+ "@typescript-eslint/eslint-plugin": "^6.7.0",
28
+ "@typescript-eslint/parser": "^6.7.0",
29
+ "eslint": "^8.50.0",
30
+ "jest": "^29.7.0",
31
+ "ts-jest": "^29.4.4",
32
+ "typescript": "^5.2.0",
33
+ "yest": "^0.0.1"
34
+ },
35
+ "dependencies": {
36
+ "axios": "^1.5.0"
37
+ },
38
+ "peerDependencies": {
39
+ "axios": "^1.5.0"
40
+ },
41
+ "files": [
42
+ "dist/**/*",
43
+ "index.d.ts",
44
+ "README.md"
45
+ ]
46
+ }
@@ -0,0 +1,84 @@
1
+ import { FieldConditionBuilder, LogicalOperator } from '../index';
2
+
3
+ describe('FieldConditionBuilder', () => {
4
+ test('should use correct operators for basic methods', () => {
5
+ const builder = new FieldConditionBuilder('name');
6
+
7
+ expect(builder.equals('John').operator).toBe('is');
8
+ expect(builder.contains('test').operator).toBe('includes');
9
+ });
10
+
11
+ test('should support dot notation in field paths', () => {
12
+ const condition = new FieldConditionBuilder('user.profile.bio').equals('Developer');
13
+ const logicalOp = LogicalOperator.Condition(condition);
14
+ const composable = logicalOp.toComposable();
15
+
16
+ const expected = {
17
+ user: {
18
+ profile: {
19
+ bio: {
20
+ is: 'Developer'
21
+ }
22
+ }
23
+ }
24
+ };
25
+
26
+ expect(composable).toEqual(expected);
27
+ });
28
+
29
+ test('should have all required operators available', () => {
30
+ const builder = new FieldConditionBuilder('test_field');
31
+
32
+ // Only test operators that actually exist in the Rust implementation
33
+ const operators = [
34
+ 'equals', 'notEquals', 'greaterThan', 'lessThan', 'greaterThanOrEqual', 'lessThanOrEqual',
35
+ 'contains', 'startsWith', 'endsWith', 'in', 'notIn', 'exists', 'notExists',
36
+ 'isNull', 'isNotNull', 'regExpMatches', 'includesCaseInsensitive',
37
+ 'startsWithCaseInsensitive', 'endsWithCaseInsensitive', 'between',
38
+ 'isLocalIp', 'isExternalIp', 'b64', 'inDataset', 'inCountry', 'cidr',
39
+ 'isTrue', 'isFalse'
40
+ ];
41
+
42
+ operators.forEach(op => {
43
+ expect(typeof (builder as any)[op]).toBe('function');
44
+ });
45
+ });
46
+
47
+ test('should support advanced operators (string, IP, misc)', () => {
48
+ const stringBuilder = new FieldConditionBuilder('text');
49
+ const regexCondition = stringBuilder.regExpMatches('^test.*');
50
+ expect(regexCondition.operator).toBe('regExpMatches');
51
+
52
+ const caseInsensitiveCondition = stringBuilder.includesCaseInsensitive('Test');
53
+ expect(caseInsensitiveCondition.operator).toBe('includesCaseInsensitive');
54
+
55
+ const ipBuilder = new FieldConditionBuilder('ip_address');
56
+ const ipLocalCondition = ipBuilder.isLocalIp();
57
+ expect(ipLocalCondition.operator).toBe('isLocalIp');
58
+
59
+ const ipExternalCondition = ipBuilder.isExternalIp();
60
+ expect(ipExternalCondition.operator).toBe('isExternalIp');
61
+
62
+ const b64Condition = ipBuilder.b64('dGVzdA==');
63
+ expect(b64Condition.operator).toBe('b64');
64
+
65
+ const countryCondition = ipBuilder.inCountry('US');
66
+ expect(countryCondition.operator).toBe('inCountry');
67
+
68
+ const cidrCondition = ipBuilder.cidr('192.168.1.0/24');
69
+ expect(cidrCondition.operator).toBe('CIDR');
70
+
71
+ const datasetCondition = ipBuilder.inDataset('malware_ips');
72
+ expect(datasetCondition.operator).toBe('inDataset');
73
+
74
+ const betweenCondition = stringBuilder.between(5, 15);
75
+ expect(betweenCondition.operator).toBe('betweenOp');
76
+ });
77
+
78
+ test('should handle empty field names gracefully', () => {
79
+ expect(() => {
80
+ const condition = new FieldConditionBuilder('').equals('test');
81
+ LogicalOperator.Condition(condition).toComposable();
82
+ }).not.toThrow();
83
+ });
84
+ });
@@ -0,0 +1,85 @@
1
+ import { FieldConditionBuilder, LogicalOperator } from '../index';
2
+
3
+ describe('LogicalOperator', () => {
4
+ test('should combine conditions with AND operator', () => {
5
+ const condition1 = new FieldConditionBuilder('user.name').equals('John');
6
+ const condition2 = new FieldConditionBuilder('user.age').greaterThan(25);
7
+
8
+ const andOp = LogicalOperator.And([
9
+ LogicalOperator.Condition(condition1),
10
+ LogicalOperator.Condition(condition2)
11
+ ]);
12
+
13
+ const composable = andOp.toComposable();
14
+
15
+ const expected = {
16
+ and: [
17
+ {
18
+ user: {
19
+ name: {
20
+ is: 'John'
21
+ }
22
+ }
23
+ },
24
+ {
25
+ user: {
26
+ age: {
27
+ greaterThan: 25
28
+ }
29
+ }
30
+ }
31
+ ]
32
+ };
33
+
34
+ expect(composable).toEqual(expected);
35
+ });
36
+
37
+ test('should combine conditions with OR operator', () => {
38
+ const condition1 = new FieldConditionBuilder('status').equals('active');
39
+ const condition2 = new FieldConditionBuilder('status').equals('pending');
40
+
41
+ const orOp = LogicalOperator.Or([
42
+ LogicalOperator.Condition(condition1),
43
+ LogicalOperator.Condition(condition2)
44
+ ]);
45
+
46
+ const composable = orOp.toComposable();
47
+
48
+ const expected = {
49
+ or: [
50
+ {
51
+ status: {
52
+ is: 'active'
53
+ }
54
+ },
55
+ {
56
+ status: {
57
+ is: 'pending'
58
+ }
59
+ }
60
+ ]
61
+ };
62
+
63
+ expect(composable).toEqual(expected);
64
+ });
65
+
66
+ test('should handle nested logical operations', () => {
67
+ const condition1 = new FieldConditionBuilder('name').equals('John');
68
+ const condition2 = new FieldConditionBuilder('age').greaterThan(25);
69
+ const condition3 = new FieldConditionBuilder('status').equals('active');
70
+
71
+ const nestedOp = LogicalOperator.Or([
72
+ LogicalOperator.And([
73
+ LogicalOperator.Condition(condition1),
74
+ LogicalOperator.Condition(condition2)
75
+ ]),
76
+ LogicalOperator.Condition(condition3)
77
+ ]);
78
+
79
+ const composable = nestedOp.toComposable();
80
+
81
+ expect(composable).toHaveProperty('or');
82
+ expect(composable.or).toHaveLength(2);
83
+ expect(composable.or[0]).toHaveProperty('and');
84
+ });
85
+ });