@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.
- package/.DS_Store +0 -0
- package/.claude/settings.local.json +8 -0
- package/.gitignore +5 -0
- package/.idea/.gitignore +5 -0
- package/.idea/compiler.xml +6 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/jsLinters/eslint.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/prettier.xml +7 -0
- package/.idea/sdk.iml +12 -0
- package/.idea/vcs.xml +6 -0
- package/.idea/workspace.xml +257 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +11 -3
- package/dist/client.js.map +1 -1
- package/dist/database.d.ts +0 -20
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +0 -40
- package/dist/database.js.map +1 -1
- package/dist/query-sdk/tests/setup.d.ts +16 -0
- package/dist/query-sdk/tests/setup.d.ts.map +1 -0
- package/dist/query-sdk/tests/setup.js +49 -0
- package/dist/query-sdk/tests/setup.js.map +1 -0
- package/examples/basic-usage.ts +136 -0
- package/examples/blob-upload-example.ts +140 -0
- package/examples/collection-schema-example.ts +304 -0
- package/examples/server-side-joins.ts +201 -0
- package/examples/tweet-self-joins-example.ts +352 -0
- package/package-lock.json +3823 -0
- package/package.json +1 -1
- package/skills.md +1096 -0
- package/src/.env +1 -0
- package/src/batch.d.ts +121 -0
- package/src/batch.js +205 -0
- package/src/batch.ts +257 -0
- package/src/client.ts +1856 -0
- package/src/database.d.ts +268 -0
- package/src/database.js +294 -0
- package/src/database.ts +695 -0
- package/src/index.d.ts +160 -0
- package/src/index.js +186 -0
- package/src/index.ts +253 -0
- package/src/query-sdk/ConditionBuilder.ts +103 -0
- package/src/query-sdk/FieldConditionBuilder.ts +2 -0
- package/src/query-sdk/NestedBuilders.ts +186 -0
- package/src/query-sdk/OnChainDB.ts +294 -0
- package/src/query-sdk/QueryBuilder.ts +1191 -0
- package/src/query-sdk/QueryResult.ts +375 -0
- package/src/query-sdk/README.md +866 -0
- package/src/query-sdk/SelectionBuilder.ts +94 -0
- package/src/query-sdk/adapters/HttpClientAdapter.ts +249 -0
- package/src/query-sdk/dist/ConditionBuilder.d.ts +22 -0
- package/src/query-sdk/dist/ConditionBuilder.js +90 -0
- package/src/query-sdk/dist/FieldConditionBuilder.d.ts +1 -0
- package/src/query-sdk/dist/FieldConditionBuilder.js +6 -0
- package/src/query-sdk/dist/NestedBuilders.d.ts +43 -0
- package/src/query-sdk/dist/NestedBuilders.js +144 -0
- package/src/query-sdk/dist/OnChainDB.d.ts +19 -0
- package/src/query-sdk/dist/OnChainDB.js +123 -0
- package/src/query-sdk/dist/QueryBuilder.d.ts +70 -0
- package/src/query-sdk/dist/QueryBuilder.js +295 -0
- package/src/query-sdk/dist/QueryResult.d.ts +52 -0
- package/src/query-sdk/dist/QueryResult.js +293 -0
- package/src/query-sdk/dist/SelectionBuilder.d.ts +20 -0
- package/src/query-sdk/dist/SelectionBuilder.js +80 -0
- package/src/query-sdk/dist/adapters/HttpClientAdapter.d.ts +27 -0
- package/src/query-sdk/dist/adapters/HttpClientAdapter.js +170 -0
- package/src/query-sdk/dist/index.d.ts +36 -0
- package/src/query-sdk/dist/index.js +27 -0
- package/src/query-sdk/dist/operators.d.ts +56 -0
- package/src/query-sdk/dist/operators.js +289 -0
- package/src/query-sdk/dist/tests/setup.d.ts +15 -0
- package/src/query-sdk/dist/tests/setup.js +46 -0
- package/src/query-sdk/index.ts +59 -0
- package/src/query-sdk/jest.config.js +25 -0
- package/src/query-sdk/operators.ts +335 -0
- package/src/query-sdk/package.json +46 -0
- package/src/query-sdk/tests/FieldConditionBuilder.test.ts +84 -0
- package/src/query-sdk/tests/LogicalOperator.test.ts +85 -0
- package/src/query-sdk/tests/NestedBuilders.test.ts +321 -0
- package/src/query-sdk/tests/QueryBuilder.test.ts +348 -0
- package/src/query-sdk/tests/QueryResult.test.ts +464 -0
- package/src/query-sdk/tests/aggregations.test.ts +653 -0
- package/src/query-sdk/tests/comprehensive.test.ts +279 -0
- package/src/query-sdk/tests/integration.test.ts +608 -0
- package/src/query-sdk/tests/operators.test.ts +327 -0
- package/src/query-sdk/tests/setup.ts +59 -0
- package/src/query-sdk/tests/unit.test.ts +794 -0
- package/src/query-sdk/tsconfig.json +26 -0
- package/src/query-sdk/yarn.lock +3092 -0
- package/src/types.d.ts +131 -0
- package/src/types.js +46 -0
- package/src/types.ts +534 -0
- package/src/x402/index.ts +12 -0
- package/src/x402/types.ts +250 -0
- package/src/x402/utils.ts +332 -0
- package/tsconfig.json +20 -0
- package/yarn.lock +2309 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {SelectionMap} from '../index';
|
|
2
|
+
|
|
3
|
+
export class SelectionBuilder {
|
|
4
|
+
private selections: SelectionMap = {};
|
|
5
|
+
|
|
6
|
+
constructor() {
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static new(): SelectionBuilder {
|
|
10
|
+
return new SelectionBuilder();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Static method to create selection that includes all fields
|
|
14
|
+
static all(): SelectionMap {
|
|
15
|
+
return {}; // Empty selection map means select all fields
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Select specific fields
|
|
19
|
+
field(fieldName: string): SelectionBuilder {
|
|
20
|
+
this.selections[fieldName] = true; // true indicates field should be included
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Select multiple fields at once
|
|
25
|
+
fields(fieldNames: string[]): SelectionBuilder {
|
|
26
|
+
fieldNames.forEach(field => {
|
|
27
|
+
this.selections[field] = true;
|
|
28
|
+
});
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Select nested fields with a builder function
|
|
33
|
+
nested<T>(fieldName: string, builderFn: (nested: SelectionBuilder) => T): SelectionBuilder {
|
|
34
|
+
const nestedBuilder = new SelectionBuilder();
|
|
35
|
+
builderFn(nestedBuilder);
|
|
36
|
+
this.selections[fieldName] = nestedBuilder.build();
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Exclude specific fields (useful when selecting most fields)
|
|
41
|
+
exclude(fieldName: string): SelectionBuilder {
|
|
42
|
+
this.selections[fieldName] = false; // false indicates field should be excluded
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Exclude multiple fields
|
|
47
|
+
excludeFields(fieldNames: string[]): SelectionBuilder {
|
|
48
|
+
fieldNames.forEach(field => {
|
|
49
|
+
this.selections[field] = false;
|
|
50
|
+
});
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Build and return the selection map
|
|
55
|
+
build(): SelectionMap {
|
|
56
|
+
return {...this.selections};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Reset the builder
|
|
60
|
+
clear(): SelectionBuilder {
|
|
61
|
+
this.selections = {};
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check if any selections have been made
|
|
66
|
+
isEmpty(): boolean {
|
|
67
|
+
return Object.keys(this.selections).length === 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Get current selection count
|
|
71
|
+
getSelectionCount(): number {
|
|
72
|
+
return Object.keys(this.selections).length;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check if a specific field is selected
|
|
76
|
+
hasField(fieldName: string): boolean {
|
|
77
|
+
return fieldName in this.selections && this.selections[fieldName] === true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check if a specific field is excluded
|
|
81
|
+
isFieldExcluded(fieldName: string): boolean {
|
|
82
|
+
return fieldName in this.selections && this.selections[fieldName] === false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Get all selected field names
|
|
86
|
+
getSelectedFields(): string[] {
|
|
87
|
+
return Object.keys(this.selections).filter(field => this.selections[field] === true);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Get all excluded field names
|
|
91
|
+
getExcludedFields(): string[] {
|
|
92
|
+
return Object.keys(this.selections).filter(field => this.selections[field] === false);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import {HttpClient} from "../index";
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
any: any;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Adapter for fetch API (works in both browser and Node.js with node-fetch)
|
|
10
|
+
export class FetchHttpClient implements HttpClient {
|
|
11
|
+
private fetchFn: typeof fetch;
|
|
12
|
+
|
|
13
|
+
constructor(fetchImplementation?: typeof fetch) {
|
|
14
|
+
// Use provided fetch implementation or global fetch
|
|
15
|
+
this.fetchFn = fetchImplementation || (globalThis.fetch?.bind(globalThis));
|
|
16
|
+
|
|
17
|
+
if (!this.fetchFn) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'Fetch is not available. Please provide a fetch implementation or use in an environment that supports fetch.'
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async post(url: string, data: any, headers: Record<string, string> = {}): Promise<any> {
|
|
25
|
+
try {
|
|
26
|
+
const response = await this.fetchFn(url, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
headers: {
|
|
29
|
+
'Content-Type': 'application/json',
|
|
30
|
+
...headers,
|
|
31
|
+
},
|
|
32
|
+
body: JSON.stringify(data),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// x402: Handle 402 Payment Required specially (not an error)
|
|
36
|
+
if (response.status === 402) {
|
|
37
|
+
const paymentData = await response.json();
|
|
38
|
+
return {
|
|
39
|
+
status: 402,
|
|
40
|
+
data: paymentData,
|
|
41
|
+
headers: Object.fromEntries(response.headers.entries())
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
const errorText = await response.text();
|
|
47
|
+
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const contentType = response.headers.get('content-type');
|
|
51
|
+
if (contentType && contentType.includes('application/json')) {
|
|
52
|
+
const jsonData = await response.json();
|
|
53
|
+
return {
|
|
54
|
+
status: response.status,
|
|
55
|
+
data: jsonData,
|
|
56
|
+
headers: Object.fromEntries(response.headers.entries())
|
|
57
|
+
};
|
|
58
|
+
} else {
|
|
59
|
+
return {
|
|
60
|
+
status: response.status,
|
|
61
|
+
data: await response.text(),
|
|
62
|
+
headers: Object.fromEntries(response.headers.entries())
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error instanceof Error) {
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
throw new Error(`Request failed: ${error}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Adapter for axios (if user prefers axios)
|
|
75
|
+
export class AxiosHttpClient implements HttpClient {
|
|
76
|
+
private axios: any;
|
|
77
|
+
|
|
78
|
+
constructor(axiosInstance: any) {
|
|
79
|
+
if (!axiosInstance) {
|
|
80
|
+
throw new Error('Axios instance is required');
|
|
81
|
+
}
|
|
82
|
+
this.axios = axiosInstance;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async post(url: string, data: any, headers: Record<string, string> = {}): Promise<any> {
|
|
86
|
+
try {
|
|
87
|
+
const response = await this.axios.post(url, data, {
|
|
88
|
+
headers: {
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
...headers,
|
|
91
|
+
},
|
|
92
|
+
validateStatus: (status: number) => status < 500 // Don't throw on 402
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Return consistent format with status and headers
|
|
96
|
+
return {
|
|
97
|
+
status: response.status,
|
|
98
|
+
data: response.data,
|
|
99
|
+
headers: response.headers || {}
|
|
100
|
+
};
|
|
101
|
+
} catch (error: any) {
|
|
102
|
+
// x402: Check if this is a 402 Payment Required error
|
|
103
|
+
if (error.response && error.response.status === 402) {
|
|
104
|
+
return {
|
|
105
|
+
status: 402,
|
|
106
|
+
data: error.response.data,
|
|
107
|
+
headers: error.response.headers || {}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (error.response) {
|
|
112
|
+
throw new Error(`HTTP ${error.response.status}: ${JSON.stringify(error.response.data)}`);
|
|
113
|
+
} else if (error.request) {
|
|
114
|
+
throw new Error('No response received from server');
|
|
115
|
+
} else {
|
|
116
|
+
throw new Error(`Request setup error: ${error.message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Simple HTTP client using Node.js built-in modules (for Node.js environments)
|
|
123
|
+
export class NodeHttpClient implements HttpClient {
|
|
124
|
+
private timeout: number;
|
|
125
|
+
|
|
126
|
+
constructor(timeout: number = 30000) {
|
|
127
|
+
this.timeout = timeout;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async post(url: string, data: any, headers: Record<string, string> = {}): Promise<any> {
|
|
131
|
+
return new Promise((resolve, reject) => {
|
|
132
|
+
const urlObj = new URL(url);
|
|
133
|
+
const isHttps = urlObj.protocol === 'https:';
|
|
134
|
+
|
|
135
|
+
// Dynamic import to avoid issues in browser environments
|
|
136
|
+
const httpModule = isHttps ? require('https') : require('http');
|
|
137
|
+
|
|
138
|
+
const postData = JSON.stringify(data);
|
|
139
|
+
|
|
140
|
+
const options = {
|
|
141
|
+
hostname: urlObj.hostname,
|
|
142
|
+
port: urlObj.port || (isHttps ? 443 : 80),
|
|
143
|
+
path: urlObj.pathname + urlObj.search,
|
|
144
|
+
method: 'POST',
|
|
145
|
+
headers: {
|
|
146
|
+
'Content-Type': 'application/json',
|
|
147
|
+
'Content-Length': Buffer.byteLength(postData),
|
|
148
|
+
...headers,
|
|
149
|
+
},
|
|
150
|
+
timeout: this.timeout,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const req = httpModule.request(options, (res: any) => {
|
|
154
|
+
let responseData = '';
|
|
155
|
+
|
|
156
|
+
res.on('data', (chunk: any) => {
|
|
157
|
+
responseData += chunk;
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
res.on('end', () => {
|
|
161
|
+
try {
|
|
162
|
+
const contentType = res.headers['content-type'] || '';
|
|
163
|
+
let parsedData;
|
|
164
|
+
|
|
165
|
+
if (contentType.includes('application/json')) {
|
|
166
|
+
parsedData = JSON.parse(responseData);
|
|
167
|
+
} else {
|
|
168
|
+
parsedData = responseData;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// x402: Handle 402 specially (not an error)
|
|
172
|
+
if (res.statusCode === 402) {
|
|
173
|
+
resolve({
|
|
174
|
+
status: 402,
|
|
175
|
+
data: parsedData,
|
|
176
|
+
headers: res.headers
|
|
177
|
+
});
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
182
|
+
resolve({
|
|
183
|
+
status: res.statusCode,
|
|
184
|
+
data: parsedData,
|
|
185
|
+
headers: res.headers
|
|
186
|
+
});
|
|
187
|
+
} else {
|
|
188
|
+
reject(new Error(`HTTP ${res.statusCode}: ${responseData}`));
|
|
189
|
+
}
|
|
190
|
+
} catch (error) {
|
|
191
|
+
reject(new Error(`Failed to parse response: ${error}`));
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
req.on('error', (error: Error) => {
|
|
197
|
+
reject(new Error(`Request failed: ${error.message}`));
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
req.on('timeout', () => {
|
|
201
|
+
req.destroy();
|
|
202
|
+
reject(new Error(`Request timed out after ${this.timeout}ms`));
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
req.write(postData);
|
|
206
|
+
req.end();
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Factory function to create appropriate HTTP client based on environment
|
|
212
|
+
export function createHttpClient(
|
|
213
|
+
options: {
|
|
214
|
+
type?: 'fetch' | 'axios' | 'node';
|
|
215
|
+
fetchImplementation?: typeof fetch;
|
|
216
|
+
axiosInstance?: any;
|
|
217
|
+
timeout?: number;
|
|
218
|
+
} = {}
|
|
219
|
+
): HttpClient {
|
|
220
|
+
const {type, fetchImplementation, axiosInstance, timeout} = options;
|
|
221
|
+
|
|
222
|
+
// Auto-detect environment if type is not specified
|
|
223
|
+
if (!type) {
|
|
224
|
+
if (typeof globalThis !== 'undefined' && typeof globalThis.fetch === 'function') {
|
|
225
|
+
return new FetchHttpClient(fetchImplementation);
|
|
226
|
+
} else { // @ts-ignore
|
|
227
|
+
if (typeof window !== 'undefined') {
|
|
228
|
+
throw new Error('Fetch is not available in this browser environment. Please provide a fetch implementation.');
|
|
229
|
+
} else {
|
|
230
|
+
// Assume Node.js environment
|
|
231
|
+
return new NodeHttpClient(timeout);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
switch (type) {
|
|
237
|
+
case 'fetch':
|
|
238
|
+
return new FetchHttpClient(fetchImplementation);
|
|
239
|
+
case 'axios':
|
|
240
|
+
if (!axiosInstance) {
|
|
241
|
+
throw new Error('Axios instance is required when using axios client');
|
|
242
|
+
}
|
|
243
|
+
return new AxiosHttpClient(axiosInstance);
|
|
244
|
+
case 'node':
|
|
245
|
+
return new NodeHttpClient(timeout);
|
|
246
|
+
default:
|
|
247
|
+
throw new Error(`Unknown HTTP client type: ${type}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { LogicalOperator, FieldConditionBuilder } from './operators';
|
|
2
|
+
import { NestedConditionBuilder } from './NestedBuilders';
|
|
3
|
+
export declare class ConditionBuilder {
|
|
4
|
+
private conditions;
|
|
5
|
+
private currentOperator?;
|
|
6
|
+
constructor();
|
|
7
|
+
static new(): ConditionBuilder;
|
|
8
|
+
field(fieldName: string): FieldConditionBuilder;
|
|
9
|
+
nested(fieldName: string, builderFn: (builder: NestedConditionBuilder) => LogicalOperator): LogicalOperator;
|
|
10
|
+
and(): ConditionBuilder;
|
|
11
|
+
or(): ConditionBuilder;
|
|
12
|
+
not(): ConditionBuilder;
|
|
13
|
+
andGroup(builderFn: (builder: ConditionBuilder) => LogicalOperator[]): LogicalOperator;
|
|
14
|
+
orGroup(builderFn: (builder: ConditionBuilder) => LogicalOperator[]): LogicalOperator;
|
|
15
|
+
notGroup(builderFn: (builder: ConditionBuilder) => LogicalOperator[]): LogicalOperator;
|
|
16
|
+
addCondition(condition: LogicalOperator): ConditionBuilder;
|
|
17
|
+
build(): LogicalOperator[];
|
|
18
|
+
buildSingle(): LogicalOperator;
|
|
19
|
+
clear(): ConditionBuilder;
|
|
20
|
+
isEmpty(): boolean;
|
|
21
|
+
getConditionCount(): number;
|
|
22
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConditionBuilder = void 0;
|
|
4
|
+
const operators_1 = require("./operators");
|
|
5
|
+
const NestedBuilders_1 = require("./NestedBuilders");
|
|
6
|
+
// Builder for creating complex conditions with logical operators
|
|
7
|
+
class ConditionBuilder {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.conditions = [];
|
|
10
|
+
}
|
|
11
|
+
static new() {
|
|
12
|
+
return new ConditionBuilder();
|
|
13
|
+
}
|
|
14
|
+
// Create a field condition builder
|
|
15
|
+
field(fieldName) {
|
|
16
|
+
return new operators_1.FieldConditionBuilder(fieldName);
|
|
17
|
+
}
|
|
18
|
+
// Create a nested field condition with fluent API (like Rust SDK)
|
|
19
|
+
nested(fieldName, builderFn) {
|
|
20
|
+
const nestedBuilder = new NestedBuilders_1.NestedConditionBuilder(fieldName);
|
|
21
|
+
return builderFn(nestedBuilder);
|
|
22
|
+
}
|
|
23
|
+
// Add an AND operator context
|
|
24
|
+
and() {
|
|
25
|
+
this.currentOperator = 'and';
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
// Add an OR operator context
|
|
29
|
+
or() {
|
|
30
|
+
this.currentOperator = 'or';
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
// Add a NOT operator context
|
|
34
|
+
not() {
|
|
35
|
+
this.currentOperator = 'not';
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
// Group conditions with AND logic
|
|
39
|
+
andGroup(builderFn) {
|
|
40
|
+
const nestedBuilder = new ConditionBuilder();
|
|
41
|
+
const conditions = builderFn(nestedBuilder);
|
|
42
|
+
return operators_1.LogicalOperator.And(conditions);
|
|
43
|
+
}
|
|
44
|
+
// Group conditions with OR logic
|
|
45
|
+
orGroup(builderFn) {
|
|
46
|
+
const nestedBuilder = new ConditionBuilder();
|
|
47
|
+
const conditions = builderFn(nestedBuilder);
|
|
48
|
+
return operators_1.LogicalOperator.Or(conditions);
|
|
49
|
+
}
|
|
50
|
+
// Group conditions with NOT logic
|
|
51
|
+
notGroup(builderFn) {
|
|
52
|
+
const nestedBuilder = new ConditionBuilder();
|
|
53
|
+
const conditions = builderFn(nestedBuilder);
|
|
54
|
+
return operators_1.LogicalOperator.Not(conditions);
|
|
55
|
+
}
|
|
56
|
+
// Add a condition to the current builder
|
|
57
|
+
addCondition(condition) {
|
|
58
|
+
this.conditions.push(condition);
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
// Build and return all conditions
|
|
62
|
+
build() {
|
|
63
|
+
return [...this.conditions];
|
|
64
|
+
}
|
|
65
|
+
// Build as a single logical operator (combines all conditions with AND by default)
|
|
66
|
+
buildSingle() {
|
|
67
|
+
if (this.conditions.length === 0) {
|
|
68
|
+
throw new Error('No conditions to build');
|
|
69
|
+
}
|
|
70
|
+
if (this.conditions.length === 1) {
|
|
71
|
+
return this.conditions[0];
|
|
72
|
+
}
|
|
73
|
+
return operators_1.LogicalOperator.And(this.conditions);
|
|
74
|
+
}
|
|
75
|
+
// Clear all conditions
|
|
76
|
+
clear() {
|
|
77
|
+
this.conditions = [];
|
|
78
|
+
this.currentOperator = undefined;
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
// Check if any conditions have been added
|
|
82
|
+
isEmpty() {
|
|
83
|
+
return this.conditions.length === 0;
|
|
84
|
+
}
|
|
85
|
+
// Get the number of conditions
|
|
86
|
+
getConditionCount() {
|
|
87
|
+
return this.conditions.length;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.ConditionBuilder = ConditionBuilder;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FieldConditionBuilder } from './operators';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FieldConditionBuilder = void 0;
|
|
4
|
+
// Re-export from operators for convenience
|
|
5
|
+
var operators_1 = require("./operators");
|
|
6
|
+
Object.defineProperty(exports, "FieldConditionBuilder", { enumerable: true, get: function () { return operators_1.FieldConditionBuilder; } });
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { LogicalOperator, Condition } from './operators';
|
|
2
|
+
export declare class NestedConditionBuilder {
|
|
3
|
+
private path;
|
|
4
|
+
constructor(rootField: string);
|
|
5
|
+
field(fieldName: string): NestedFieldConditionBuilder;
|
|
6
|
+
nested(fieldName: string, builderFn: (builder: NestedConditionBuilder) => LogicalOperator): LogicalOperator;
|
|
7
|
+
andGroup(builderFn: (builder: NestedConditionBuilder) => LogicalOperator[]): LogicalOperator;
|
|
8
|
+
orGroup(builderFn: (builder: NestedConditionBuilder) => LogicalOperator[]): LogicalOperator;
|
|
9
|
+
notGroup(builderFn: (builder: NestedConditionBuilder) => LogicalOperator[]): LogicalOperator;
|
|
10
|
+
}
|
|
11
|
+
export declare class NestedFieldConditionBuilder {
|
|
12
|
+
private fieldPath;
|
|
13
|
+
constructor(fieldPath: string[]);
|
|
14
|
+
private createCondition;
|
|
15
|
+
equals(value: any): Condition;
|
|
16
|
+
notEquals(value: any): Condition;
|
|
17
|
+
in(values: any[]): Condition;
|
|
18
|
+
notIn(values: any[]): Condition;
|
|
19
|
+
isNull(): Condition;
|
|
20
|
+
isNotNull(): Condition;
|
|
21
|
+
exists(): Condition;
|
|
22
|
+
notExists(): Condition;
|
|
23
|
+
startsWith(value: string): Condition;
|
|
24
|
+
endsWith(value: string): Condition;
|
|
25
|
+
contains(value: string): Condition;
|
|
26
|
+
regExpMatches(pattern: string): Condition;
|
|
27
|
+
includesCaseInsensitive(value: string): Condition;
|
|
28
|
+
startsWithCaseInsensitive(value: string): Condition;
|
|
29
|
+
endsWithCaseInsensitive(value: string): Condition;
|
|
30
|
+
greaterThan(value: any): Condition;
|
|
31
|
+
lessThan(value: any): Condition;
|
|
32
|
+
greaterThanOrEqual(value: any): Condition;
|
|
33
|
+
lessThanOrEqual(value: any): Condition;
|
|
34
|
+
isLocalIp(): Condition;
|
|
35
|
+
isExternalIp(): Condition;
|
|
36
|
+
b64(value: string): Condition;
|
|
37
|
+
inDataset(dataset: string): Condition;
|
|
38
|
+
inCountry(countryCode: string): Condition;
|
|
39
|
+
cidr(cidr: string): Condition;
|
|
40
|
+
between(min: any, max: any): Condition;
|
|
41
|
+
isTrue(): Condition;
|
|
42
|
+
isFalse(): Condition;
|
|
43
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NestedFieldConditionBuilder = exports.NestedConditionBuilder = void 0;
|
|
4
|
+
const operators_1 = require("./operators");
|
|
5
|
+
// Builder for creating nested field conditions with ORM-like syntax
|
|
6
|
+
class NestedConditionBuilder {
|
|
7
|
+
constructor(rootField) {
|
|
8
|
+
this.path = [rootField];
|
|
9
|
+
}
|
|
10
|
+
// Add another level to the path and create field conditions
|
|
11
|
+
field(fieldName) {
|
|
12
|
+
const newPath = [...this.path, fieldName];
|
|
13
|
+
return new NestedFieldConditionBuilder(newPath);
|
|
14
|
+
}
|
|
15
|
+
// Create nested structure with callback
|
|
16
|
+
nested(fieldName, builderFn) {
|
|
17
|
+
const nestedPath = [...this.path, fieldName];
|
|
18
|
+
const nestedBuilder = new NestedConditionBuilder('');
|
|
19
|
+
nestedBuilder.path = nestedPath;
|
|
20
|
+
return builderFn(nestedBuilder);
|
|
21
|
+
}
|
|
22
|
+
// Create logical groups
|
|
23
|
+
andGroup(builderFn) {
|
|
24
|
+
const conditions = builderFn(this);
|
|
25
|
+
return operators_1.LogicalOperator.And(conditions);
|
|
26
|
+
}
|
|
27
|
+
orGroup(builderFn) {
|
|
28
|
+
const conditions = builderFn(this);
|
|
29
|
+
return operators_1.LogicalOperator.Or(conditions);
|
|
30
|
+
}
|
|
31
|
+
notGroup(builderFn) {
|
|
32
|
+
const conditions = builderFn(this);
|
|
33
|
+
return operators_1.LogicalOperator.Not(conditions);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.NestedConditionBuilder = NestedConditionBuilder;
|
|
37
|
+
// Builder for field conditions within nested structures
|
|
38
|
+
// Only includes operators that actually exist in the Rust implementation
|
|
39
|
+
class NestedFieldConditionBuilder {
|
|
40
|
+
constructor(fieldPath) {
|
|
41
|
+
this.fieldPath = fieldPath;
|
|
42
|
+
}
|
|
43
|
+
createCondition(operator, value) {
|
|
44
|
+
const path = this.fieldPath.join('.');
|
|
45
|
+
return {
|
|
46
|
+
field: path,
|
|
47
|
+
operator,
|
|
48
|
+
value
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// ===== BASE OPERATORS (BaseOperator) =====
|
|
52
|
+
equals(value) {
|
|
53
|
+
return this.createCondition('is', value);
|
|
54
|
+
}
|
|
55
|
+
notEquals(value) {
|
|
56
|
+
return this.createCondition('isNot', value);
|
|
57
|
+
}
|
|
58
|
+
in(values) {
|
|
59
|
+
return this.createCondition('in', values);
|
|
60
|
+
}
|
|
61
|
+
notIn(values) {
|
|
62
|
+
return this.createCondition('notIn', values);
|
|
63
|
+
}
|
|
64
|
+
isNull() {
|
|
65
|
+
return this.createCondition('isNull', true);
|
|
66
|
+
}
|
|
67
|
+
isNotNull() {
|
|
68
|
+
return this.createCondition('isNull', false);
|
|
69
|
+
}
|
|
70
|
+
exists() {
|
|
71
|
+
return this.createCondition('exists', true);
|
|
72
|
+
}
|
|
73
|
+
notExists() {
|
|
74
|
+
return this.createCondition('exists', false);
|
|
75
|
+
}
|
|
76
|
+
// ===== STRING OPERATORS (StringOperator) =====
|
|
77
|
+
startsWith(value) {
|
|
78
|
+
return this.createCondition('startsWith', value);
|
|
79
|
+
}
|
|
80
|
+
endsWith(value) {
|
|
81
|
+
return this.createCondition('endsWith', value);
|
|
82
|
+
}
|
|
83
|
+
contains(value) {
|
|
84
|
+
return this.createCondition('includes', value);
|
|
85
|
+
}
|
|
86
|
+
regExpMatches(pattern) {
|
|
87
|
+
return this.createCondition('regExpMatches', pattern);
|
|
88
|
+
}
|
|
89
|
+
includesCaseInsensitive(value) {
|
|
90
|
+
return this.createCondition('includesCaseInsensitive', value);
|
|
91
|
+
}
|
|
92
|
+
startsWithCaseInsensitive(value) {
|
|
93
|
+
return this.createCondition('startsWithCaseInsensitive', value);
|
|
94
|
+
}
|
|
95
|
+
endsWithCaseInsensitive(value) {
|
|
96
|
+
return this.createCondition('endsWithCaseInsensitive', value);
|
|
97
|
+
}
|
|
98
|
+
// ===== NUMBER OPERATORS (NumberOperator) =====
|
|
99
|
+
greaterThan(value) {
|
|
100
|
+
return this.createCondition('greaterThan', value);
|
|
101
|
+
}
|
|
102
|
+
lessThan(value) {
|
|
103
|
+
return this.createCondition('lessThan', value);
|
|
104
|
+
}
|
|
105
|
+
greaterThanOrEqual(value) {
|
|
106
|
+
return this.createCondition('greaterThanOrEqual', value);
|
|
107
|
+
}
|
|
108
|
+
lessThanOrEqual(value) {
|
|
109
|
+
return this.createCondition('lessThanOrEqual', value);
|
|
110
|
+
}
|
|
111
|
+
// ===== IP OPERATORS (IpOperator) =====
|
|
112
|
+
isLocalIp() {
|
|
113
|
+
return this.createCondition('isLocalIp', true);
|
|
114
|
+
}
|
|
115
|
+
isExternalIp() {
|
|
116
|
+
return this.createCondition('isExternalIp', true);
|
|
117
|
+
}
|
|
118
|
+
// ===== MISC OPERATORS (MiscOperator) =====
|
|
119
|
+
b64(value) {
|
|
120
|
+
return this.createCondition('b64', value);
|
|
121
|
+
}
|
|
122
|
+
inDataset(dataset) {
|
|
123
|
+
return this.createCondition('inDataset', dataset);
|
|
124
|
+
}
|
|
125
|
+
inCountry(countryCode) {
|
|
126
|
+
return this.createCondition('inCountry', countryCode);
|
|
127
|
+
}
|
|
128
|
+
cidr(cidr) {
|
|
129
|
+
return this.createCondition('CIDR', cidr);
|
|
130
|
+
}
|
|
131
|
+
// ===== BETWEEN OPERATOR =====
|
|
132
|
+
between(min, max) {
|
|
133
|
+
return this.createCondition('betweenOp', { from: min, to: max });
|
|
134
|
+
}
|
|
135
|
+
// ===== CONVENIENCE METHODS =====
|
|
136
|
+
// Boolean checks (using base operators)
|
|
137
|
+
isTrue() {
|
|
138
|
+
return this.equals(true);
|
|
139
|
+
}
|
|
140
|
+
isFalse() {
|
|
141
|
+
return this.equals(false);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
exports.NestedFieldConditionBuilder = NestedFieldConditionBuilder;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { QueryBuilder } from './QueryBuilder';
|
|
2
|
+
import { SelectionBuilder } from './SelectionBuilder';
|
|
3
|
+
import { FieldMap, HttpClient, QueryResponse } from "./index";
|
|
4
|
+
export declare class OnChainDB {
|
|
5
|
+
private static httpClient?;
|
|
6
|
+
private static serverUrl?;
|
|
7
|
+
static configure(httpClient: HttpClient, serverUrl: string): void;
|
|
8
|
+
static getHttpClient(): HttpClient | undefined;
|
|
9
|
+
static getServerUrl(): string | undefined;
|
|
10
|
+
static query(): QueryBuilder;
|
|
11
|
+
static queryWith(httpClient: HttpClient, serverUrl: string): QueryBuilder;
|
|
12
|
+
static select(builderFn: (builder: SelectionBuilder) => SelectionBuilder): QueryBuilder;
|
|
13
|
+
static rawQuery(queryJson: string, httpClient?: HttpClient, serverUrl?: string, fieldMap?: FieldMap): Promise<QueryResponse>;
|
|
14
|
+
static queryFromJson(queryObject: any, httpClient?: HttpClient, serverUrl?: string): Promise<QueryResponse>;
|
|
15
|
+
static healthCheck(httpClient?: HttpClient, serverUrl?: string): Promise<boolean>;
|
|
16
|
+
static serverInfo(httpClient?: HttpClient, serverUrl?: string): Promise<any>;
|
|
17
|
+
static reset(): void;
|
|
18
|
+
static isConfigured(): boolean;
|
|
19
|
+
}
|