@onchaindb/sdk 0.4.5 → 2.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.
- package/.claude/settings.local.json +10 -2
- package/README.md +422 -355
- package/dist/batch.d.ts +1 -10
- package/dist/batch.d.ts.map +1 -1
- package/dist/batch.js +4 -26
- package/dist/batch.js.map +1 -1
- package/dist/client.d.ts +31 -46
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +222 -357
- package/dist/client.js.map +1 -1
- package/dist/database.d.ts +14 -131
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +35 -131
- package/dist/database.js.map +1 -1
- package/dist/index.d.ts +10 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -18
- package/dist/index.js.map +1 -1
- package/dist/query-sdk/ConditionBuilder.d.ts +3 -11
- package/dist/query-sdk/ConditionBuilder.d.ts.map +1 -1
- package/dist/query-sdk/ConditionBuilder.js +10 -48
- package/dist/query-sdk/ConditionBuilder.js.map +1 -1
- package/dist/query-sdk/NestedBuilders.d.ts +33 -30
- package/dist/query-sdk/NestedBuilders.d.ts.map +1 -1
- package/dist/query-sdk/NestedBuilders.js +46 -43
- package/dist/query-sdk/NestedBuilders.js.map +1 -1
- package/{src/query-sdk/dist/OnChainDB.d.ts → dist/query-sdk/OnDB.d.ts} +10 -2
- package/dist/query-sdk/OnDB.d.ts.map +1 -0
- package/{src/query-sdk/dist/OnChainDB.js → dist/query-sdk/OnDB.js} +86 -18
- package/dist/query-sdk/OnDB.js.map +1 -0
- package/dist/query-sdk/QueryBuilder.d.ts +4 -2
- package/dist/query-sdk/QueryBuilder.d.ts.map +1 -1
- package/dist/query-sdk/QueryBuilder.js +47 -169
- package/dist/query-sdk/QueryBuilder.js.map +1 -1
- package/dist/query-sdk/QueryResult.d.ts +0 -38
- package/dist/query-sdk/QueryResult.d.ts.map +1 -1
- package/dist/query-sdk/QueryResult.js +1 -227
- package/dist/query-sdk/QueryResult.js.map +1 -1
- package/dist/query-sdk/index.d.ts +2 -2
- package/dist/query-sdk/index.d.ts.map +1 -1
- package/dist/query-sdk/index.js +3 -3
- package/dist/query-sdk/index.js.map +1 -1
- package/dist/query-sdk/operators.d.ts +32 -28
- package/dist/query-sdk/operators.d.ts.map +1 -1
- package/dist/query-sdk/operators.js +45 -155
- package/dist/query-sdk/operators.js.map +1 -1
- package/dist/types.d.ts +159 -36
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +8 -8
- package/dist/types.js.map +1 -1
- package/dist/x402/types.d.ts +1 -1
- package/dist/x402/types.d.ts.map +1 -1
- package/dist/x402/utils.js +2 -2
- package/dist/x402/utils.js.map +1 -1
- package/jest.config.js +4 -0
- package/package.json +1 -1
- package/skills.md +0 -1
- package/src/batch.d.ts +3 -3
- package/src/batch.js +1 -1
- package/src/client.ts +287 -823
- package/src/database.d.ts +1 -1
- package/src/database.js +4 -4
- package/src/database.ts +71 -494
- package/src/index.d.ts +18 -18
- package/src/index.js +16 -16
- package/src/index.ts +44 -198
- package/src/query-sdk/ConditionBuilder.ts +37 -89
- package/src/query-sdk/NestedBuilders.ts +90 -92
- package/src/query-sdk/{OnChainDB.ts → OnDB.ts} +1 -1
- package/src/query-sdk/QueryBuilder.ts +59 -218
- package/src/query-sdk/QueryResult.ts +4 -330
- package/src/query-sdk/README.md +218 -587
- package/src/query-sdk/index.ts +2 -2
- package/src/query-sdk/operators.ts +91 -200
- package/src/query-sdk/tests/FieldConditionBuilder.test.ts +70 -71
- package/src/query-sdk/tests/LogicalOperator.test.ts +43 -82
- package/src/query-sdk/tests/NestedBuilders.test.ts +229 -309
- package/src/query-sdk/tests/QueryBuilder.test.ts +5 -5
- package/src/query-sdk/tests/QueryResult.test.ts +41 -435
- package/src/query-sdk/tests/comprehensive.test.ts +4 -185
- package/src/tests/client-requests.test.ts +280 -0
- package/src/tests/client-validation.test.ts +80 -0
- package/src/types.d.ts +6 -6
- package/src/types.js +8 -8
- package/src/types.ts +239 -54
- package/src/x402/types.ts +3 -3
- package/src/x402/utils.ts +3 -3
- package/examples/blob-upload-example.ts +0 -140
- package/src/batch.ts +0 -257
- package/src/query-sdk/dist/ConditionBuilder.d.ts +0 -22
- package/src/query-sdk/dist/ConditionBuilder.js +0 -90
- package/src/query-sdk/dist/FieldConditionBuilder.d.ts +0 -1
- package/src/query-sdk/dist/FieldConditionBuilder.js +0 -6
- package/src/query-sdk/dist/NestedBuilders.d.ts +0 -43
- package/src/query-sdk/dist/NestedBuilders.js +0 -144
- package/src/query-sdk/dist/QueryBuilder.d.ts +0 -70
- package/src/query-sdk/dist/QueryBuilder.js +0 -295
- package/src/query-sdk/dist/QueryResult.d.ts +0 -52
- package/src/query-sdk/dist/QueryResult.js +0 -293
- package/src/query-sdk/dist/SelectionBuilder.d.ts +0 -20
- package/src/query-sdk/dist/SelectionBuilder.js +0 -80
- package/src/query-sdk/dist/adapters/HttpClientAdapter.d.ts +0 -27
- package/src/query-sdk/dist/adapters/HttpClientAdapter.js +0 -170
- package/src/query-sdk/dist/index.d.ts +0 -36
- package/src/query-sdk/dist/index.js +0 -27
- package/src/query-sdk/dist/operators.d.ts +0 -56
- package/src/query-sdk/dist/operators.js +0 -289
- package/src/query-sdk/dist/tests/setup.d.ts +0 -15
- package/src/query-sdk/dist/tests/setup.js +0 -46
- package/src/query-sdk/jest.config.js +0 -25
- package/src/query-sdk/package.json +0 -46
- package/src/query-sdk/tests/aggregations.test.ts +0 -653
- package/src/query-sdk/tests/integration.test.ts +0 -608
- package/src/query-sdk/tests/operators.test.ts +0 -327
- package/src/query-sdk/tests/unit.test.ts +0 -794
- package/src/query-sdk/tsconfig.json +0 -26
- package/src/query-sdk/yarn.lock +0 -3092
package/dist/client.js
CHANGED
|
@@ -3,23 +3,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.OnDBClient = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
const eventemitter3_1 = require("eventemitter3");
|
|
9
9
|
const types_1 = require("./types");
|
|
10
10
|
const database_1 = require("./database");
|
|
11
11
|
const query_sdk_1 = require("./query-sdk");
|
|
12
12
|
const x402_1 = require("./x402");
|
|
13
|
-
class
|
|
13
|
+
class OnDBClient extends eventemitter3_1.EventEmitter {
|
|
14
14
|
constructor(config) {
|
|
15
15
|
super();
|
|
16
16
|
const appKey = config.appKey || '';
|
|
17
17
|
const userKey = config.userKey || '';
|
|
18
|
+
const agentKey = config.agentKey || '';
|
|
18
19
|
this.config = {
|
|
19
20
|
endpoint: config.endpoint,
|
|
20
21
|
apiKey: config.apiKey || "",
|
|
21
22
|
appKey: appKey,
|
|
22
23
|
userKey: userKey,
|
|
24
|
+
agentKey: agentKey,
|
|
23
25
|
appId: config.appId || undefined,
|
|
24
26
|
timeout: config.timeout || 30000,
|
|
25
27
|
retryCount: config.retryCount || 3,
|
|
@@ -37,6 +39,9 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
37
39
|
if (userKey) {
|
|
38
40
|
headers['X-User-Key'] = userKey;
|
|
39
41
|
}
|
|
42
|
+
if (agentKey) {
|
|
43
|
+
headers['X-Agent-Key'] = agentKey;
|
|
44
|
+
}
|
|
40
45
|
this.http = axios_1.default.create({
|
|
41
46
|
baseURL: this.config.endpoint,
|
|
42
47
|
timeout: this.config.timeout,
|
|
@@ -44,8 +49,12 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
44
49
|
});
|
|
45
50
|
}
|
|
46
51
|
database(appId) {
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
const resolvedAppId = appId || this.config.appId;
|
|
53
|
+
if (!resolvedAppId) {
|
|
54
|
+
throw new types_1.ValidationError('appId must be provided either in config or as an argument to database()');
|
|
55
|
+
}
|
|
56
|
+
if (!this._database || this._database['appId'] !== resolvedAppId) {
|
|
57
|
+
this._database = (0, database_1.createDatabaseManager)(this.http, resolvedAppId, this.config.apiKey);
|
|
49
58
|
}
|
|
50
59
|
return this._database;
|
|
51
60
|
}
|
|
@@ -56,7 +65,7 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
56
65
|
x402Response = (0, x402_1.parseX402Response)(response.data);
|
|
57
66
|
}
|
|
58
67
|
catch (e) {
|
|
59
|
-
throw new types_1.
|
|
68
|
+
throw new types_1.OnDBError(`Invalid x402 response: ${e instanceof Error ? e.message : String(e)}`, 'PAYMENT_ERROR', 402);
|
|
60
69
|
}
|
|
61
70
|
const requirement = (0, x402_1.selectPaymentOption)(x402Response.accepts);
|
|
62
71
|
const quote = (0, x402_1.requirementToQuote)(requirement, x402Response.accepts);
|
|
@@ -69,7 +78,7 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
69
78
|
paymentMethod: quote.paymentMethod,
|
|
70
79
|
});
|
|
71
80
|
if (!paymentCallback) {
|
|
72
|
-
throw new types_1.
|
|
81
|
+
throw new types_1.OnDBError('Payment required but no payment callback provided. Please provide a payment callback to handle x402.', 'PAYMENT_REQUIRED', 402, quote);
|
|
73
82
|
}
|
|
74
83
|
console.log('[x402] Calling payment callback...');
|
|
75
84
|
const payment = await paymentCallback(quote);
|
|
@@ -79,7 +88,7 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
79
88
|
const facilitatorPayment = payment;
|
|
80
89
|
const selectedRequirement = x402Response.accepts.find((req) => req.network === facilitatorPayment.network);
|
|
81
90
|
if (!selectedRequirement) {
|
|
82
|
-
throw new types_1.
|
|
91
|
+
throw new types_1.OnDBError(`Payment callback returned network '${facilitatorPayment.network}' but no matching payment option found`, 'PAYMENT_ERROR');
|
|
83
92
|
}
|
|
84
93
|
console.log('[x402] Using payment option for network:', selectedRequirement.network);
|
|
85
94
|
if (facilitatorPayment.evmAuthorization) {
|
|
@@ -96,7 +105,7 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
96
105
|
});
|
|
97
106
|
}
|
|
98
107
|
else {
|
|
99
|
-
throw new types_1.
|
|
108
|
+
throw new types_1.OnDBError('Facilitator payment missing authorization data', 'PAYMENT_ERROR');
|
|
100
109
|
}
|
|
101
110
|
}
|
|
102
111
|
else {
|
|
@@ -115,31 +124,15 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
115
124
|
if (serverResult.ticket_id) {
|
|
116
125
|
if (waitForConfirmation) {
|
|
117
126
|
const taskInfo = await this.waitForTaskCompletion(serverResult.ticket_id);
|
|
118
|
-
if (taskInfo.result
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
id: firstResult.id,
|
|
122
|
-
block_height: firstResult.celestia_height || 0,
|
|
123
|
-
transaction_hash: firstResult.blob_id || '',
|
|
124
|
-
celestia_height: firstResult.celestia_height || 0,
|
|
125
|
-
namespace: firstResult.namespace || '',
|
|
126
|
-
confirmed: firstResult.celestia_height > 0
|
|
127
|
-
};
|
|
127
|
+
if (taskInfo.result?.results?.length > 0) {
|
|
128
|
+
return this.buildStoreResult(taskInfo.result.results[0]);
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
else {
|
|
131
|
-
return {
|
|
132
|
-
id: serverResult.ticket_id,
|
|
133
|
-
block_height: 0,
|
|
134
|
-
transaction_hash: '',
|
|
135
|
-
celestia_height: 0,
|
|
136
|
-
namespace: '',
|
|
137
|
-
confirmed: false,
|
|
138
|
-
ticket_id: serverResult.ticket_id
|
|
139
|
-
};
|
|
132
|
+
return { id: serverResult.ticket_id, block_height: 0, transaction_hash: '', celestia_height: 0, namespace: '', confirmed: false, ticket_id: serverResult.ticket_id };
|
|
140
133
|
}
|
|
141
134
|
}
|
|
142
|
-
throw new types_1.
|
|
135
|
+
throw new types_1.OnDBError('No ticket_id in response after payment', 'STORE_ERROR');
|
|
143
136
|
}
|
|
144
137
|
async store(request, paymentCallback, waitForConfirmation = true) {
|
|
145
138
|
this.validateStoreRequest(request);
|
|
@@ -150,12 +143,6 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
150
143
|
try {
|
|
151
144
|
delete resolvedRequest.collection;
|
|
152
145
|
const response = await this.http.post('/store', resolvedRequest);
|
|
153
|
-
if (response.status === 402 && response.data) {
|
|
154
|
-
const v = await this.handleX402(response, paymentCallback, resolvedRequest, waitForConfirmation);
|
|
155
|
-
if (v) {
|
|
156
|
-
return v;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
146
|
const serverResult = response.data;
|
|
160
147
|
if (serverResult.ticket_id) {
|
|
161
148
|
this.emit('transaction:queued', {
|
|
@@ -165,16 +152,8 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
165
152
|
});
|
|
166
153
|
if (waitForConfirmation) {
|
|
167
154
|
const taskInfo = await this.waitForTaskCompletion(serverResult.ticket_id);
|
|
168
|
-
if (taskInfo.result
|
|
169
|
-
const
|
|
170
|
-
const result = {
|
|
171
|
-
id: firstResult.id,
|
|
172
|
-
block_height: firstResult.celestia_height || 0,
|
|
173
|
-
transaction_hash: firstResult.blob_id || '',
|
|
174
|
-
celestia_height: firstResult.celestia_height || 0,
|
|
175
|
-
namespace: firstResult.namespace || '',
|
|
176
|
-
confirmed: firstResult.celestia_height > 0
|
|
177
|
-
};
|
|
155
|
+
if (taskInfo.result?.results?.length > 0) {
|
|
156
|
+
const result = this.buildStoreResult(taskInfo.result.results[0]);
|
|
178
157
|
this.emit('transaction:confirmed', {
|
|
179
158
|
id: result.id,
|
|
180
159
|
status: 'confirmed',
|
|
@@ -185,33 +164,18 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
185
164
|
return result;
|
|
186
165
|
}
|
|
187
166
|
else {
|
|
188
|
-
throw new types_1.
|
|
167
|
+
throw new types_1.OnDBError('Task completed but no storage results found', 'STORE_ERROR');
|
|
189
168
|
}
|
|
190
169
|
}
|
|
191
170
|
else {
|
|
192
|
-
return {
|
|
193
|
-
id: serverResult.ticket_id,
|
|
194
|
-
block_height: 0,
|
|
195
|
-
transaction_hash: '',
|
|
196
|
-
celestia_height: 0,
|
|
197
|
-
namespace: '',
|
|
198
|
-
confirmed: false,
|
|
199
|
-
ticket_id: serverResult.ticket_id
|
|
200
|
-
};
|
|
171
|
+
return { id: serverResult.ticket_id, block_height: 0, transaction_hash: '', celestia_height: 0, namespace: '', confirmed: false, ticket_id: serverResult.ticket_id };
|
|
201
172
|
}
|
|
202
173
|
}
|
|
203
|
-
const firstResult = serverResult.results
|
|
174
|
+
const firstResult = serverResult.results?.[0];
|
|
204
175
|
if (!firstResult) {
|
|
205
|
-
throw new types_1.
|
|
176
|
+
throw new types_1.OnDBError('No results returned from server', 'STORE_ERROR');
|
|
206
177
|
}
|
|
207
|
-
const result =
|
|
208
|
-
id: firstResult.id,
|
|
209
|
-
block_height: firstResult.celestia_height || 0,
|
|
210
|
-
transaction_hash: firstResult.blob_id || '',
|
|
211
|
-
celestia_height: firstResult.celestia_height || 0,
|
|
212
|
-
namespace: firstResult.namespace || '',
|
|
213
|
-
confirmed: firstResult.celestia_height > 0
|
|
214
|
-
};
|
|
178
|
+
const result = this.buildStoreResult(firstResult);
|
|
215
179
|
if (result.block_height === 0) {
|
|
216
180
|
this.emit('transaction:pending', {
|
|
217
181
|
id: result.id,
|
|
@@ -229,9 +193,6 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
229
193
|
celestia_height: result.celestia_height
|
|
230
194
|
});
|
|
231
195
|
}
|
|
232
|
-
if (waitForConfirmation && result.block_height === 0) {
|
|
233
|
-
return await this.waitForConfirmation(result.transaction_hash);
|
|
234
|
-
}
|
|
235
196
|
return result;
|
|
236
197
|
}
|
|
237
198
|
catch (error) {
|
|
@@ -243,69 +204,15 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
243
204
|
return v;
|
|
244
205
|
}
|
|
245
206
|
}
|
|
246
|
-
throw new types_1.
|
|
207
|
+
throw new types_1.OnDBError(JSON.stringify(err.response?.data), 'STORE_ERROR');
|
|
247
208
|
}
|
|
248
209
|
console.error(error);
|
|
249
|
-
const dbError = error instanceof types_1.
|
|
250
|
-
new types_1.
|
|
210
|
+
const dbError = error instanceof types_1.OnDBError ? error :
|
|
211
|
+
new types_1.OnDBError(error.message, 'STORE_ERROR');
|
|
251
212
|
this.emit('error', dbError);
|
|
252
213
|
throw dbError;
|
|
253
214
|
}
|
|
254
215
|
}
|
|
255
|
-
async storeAndConfirm(request) {
|
|
256
|
-
return this.store(request, undefined, true);
|
|
257
|
-
}
|
|
258
|
-
async waitForConfirmation(transactionHash, maxWaitTime = 300000) {
|
|
259
|
-
const startTime = Date.now();
|
|
260
|
-
const pollInterval = 3000;
|
|
261
|
-
console.log(`🔄 Waiting for transaction ${transactionHash} confirmation...`);
|
|
262
|
-
while (Date.now() - startTime < maxWaitTime) {
|
|
263
|
-
try {
|
|
264
|
-
const rpcUrl = 'https://celestia-mocha-rpc.publicnode.com:443';
|
|
265
|
-
const txUrl = `${rpcUrl}/tx?hash=0x${transactionHash}`;
|
|
266
|
-
console.log(`🔍 Checking transaction status: attempt ${Math.floor((Date.now() - startTime) / pollInterval) + 1}`);
|
|
267
|
-
const response = await axios_1.default.get(txUrl);
|
|
268
|
-
if (response.data?.result && response.data.result !== null) {
|
|
269
|
-
const txResult = response.data.result;
|
|
270
|
-
const height = parseInt(txResult.height);
|
|
271
|
-
if (height > 0) {
|
|
272
|
-
console.log(`✅ Transaction ${transactionHash} confirmed at height ${height}`);
|
|
273
|
-
const confirmedTx = {
|
|
274
|
-
id: transactionHash,
|
|
275
|
-
namespace: '',
|
|
276
|
-
block_height: height,
|
|
277
|
-
transaction_hash: transactionHash,
|
|
278
|
-
celestia_height: height,
|
|
279
|
-
confirmed: true
|
|
280
|
-
};
|
|
281
|
-
this.emit('transaction:confirmed', {
|
|
282
|
-
id: transactionHash,
|
|
283
|
-
status: 'confirmed',
|
|
284
|
-
block_height: height,
|
|
285
|
-
transaction_hash: transactionHash
|
|
286
|
-
});
|
|
287
|
-
return confirmedTx;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
console.log(`⏳ Transaction still pending, waiting ${pollInterval}ms...`);
|
|
291
|
-
this.emit('transaction:pending', {
|
|
292
|
-
id: transactionHash,
|
|
293
|
-
status: 'pending',
|
|
294
|
-
block_height: 0,
|
|
295
|
-
transaction_hash: transactionHash
|
|
296
|
-
});
|
|
297
|
-
await this.sleep(pollInterval);
|
|
298
|
-
}
|
|
299
|
-
catch (error) {
|
|
300
|
-
if (Date.now() - startTime >= maxWaitTime) {
|
|
301
|
-
throw new types_1.TransactionError(`Transaction confirmation timeout after ${maxWaitTime}ms`, transactionHash);
|
|
302
|
-
}
|
|
303
|
-
console.log(`⚠️ Error checking transaction (will retry): ${error}`);
|
|
304
|
-
await this.sleep(pollInterval);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
throw new types_1.TransactionError(`Transaction confirmation timeout after ${maxWaitTime}ms`, transactionHash);
|
|
308
|
-
}
|
|
309
216
|
async createIndex(request) {
|
|
310
217
|
try {
|
|
311
218
|
const appId = this.config.appId || 'default';
|
|
@@ -313,8 +220,8 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
313
220
|
return response.data;
|
|
314
221
|
}
|
|
315
222
|
catch (error) {
|
|
316
|
-
throw error instanceof types_1.
|
|
317
|
-
new types_1.
|
|
223
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
224
|
+
new types_1.OnDBError('Failed to create index', 'INDEX_ERROR');
|
|
318
225
|
}
|
|
319
226
|
}
|
|
320
227
|
async createCollection(schema) {
|
|
@@ -330,7 +237,7 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
330
237
|
};
|
|
331
238
|
const allFields = {};
|
|
332
239
|
if (schema.useBaseFields !== false) {
|
|
333
|
-
Object.assign(allFields,
|
|
240
|
+
Object.assign(allFields, OnDBClient.BASE_FIELDS);
|
|
334
241
|
}
|
|
335
242
|
Object.assign(allFields, schema.fields);
|
|
336
243
|
for (const [fieldName, fieldDef] of Object.entries(allFields)) {
|
|
@@ -391,21 +298,9 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
391
298
|
success: true,
|
|
392
299
|
errors: []
|
|
393
300
|
};
|
|
394
|
-
let existingIndexes = [];
|
|
395
|
-
try {
|
|
396
|
-
const response = await this.http.get(`/api/apps/${appId}/collections/${schema.name}/indexes`);
|
|
397
|
-
existingIndexes = response.data?.indexes || response.data || [];
|
|
398
|
-
}
|
|
399
|
-
catch (error) {
|
|
400
|
-
existingIndexes = [];
|
|
401
|
-
}
|
|
402
|
-
const existingByField = new Map();
|
|
403
|
-
for (const idx of existingIndexes) {
|
|
404
|
-
existingByField.set(idx.field_name, { type: idx.index_type, name: idx.name });
|
|
405
|
-
}
|
|
406
301
|
const allFields = {};
|
|
407
302
|
if (schema.useBaseFields !== false) {
|
|
408
|
-
Object.assign(allFields,
|
|
303
|
+
Object.assign(allFields, OnDBClient.BASE_FIELDS);
|
|
409
304
|
}
|
|
410
305
|
Object.assign(allFields, schema.fields);
|
|
411
306
|
const desiredIndexedFields = new Set();
|
|
@@ -415,7 +310,7 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
415
310
|
}
|
|
416
311
|
}
|
|
417
312
|
for (const fieldName of desiredIndexedFields) {
|
|
418
|
-
|
|
313
|
+
{
|
|
419
314
|
const fieldDef = allFields[fieldName];
|
|
420
315
|
const indexType = fieldDef.indexType || this.getDefaultIndexType(fieldDef.type);
|
|
421
316
|
try {
|
|
@@ -449,232 +344,227 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
449
344
|
}
|
|
450
345
|
}
|
|
451
346
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
await this.http.delete(`/api/apps/${appId}/indexes/${indexId}`);
|
|
457
|
-
result.removed.push({
|
|
458
|
-
field: fieldName,
|
|
459
|
-
type: existing.type
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
catch (error) {
|
|
463
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
464
|
-
result.errors.push(`Failed to remove index on ${fieldName}: ${errorMsg}`);
|
|
465
|
-
result.success = false;
|
|
466
|
-
}
|
|
347
|
+
if (schema.sharding) {
|
|
348
|
+
try {
|
|
349
|
+
await this.setupSharding(schema.name, schema.sharding);
|
|
350
|
+
result.sharding_configured = true;
|
|
467
351
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
result.
|
|
472
|
-
field: fieldName,
|
|
473
|
-
type: existing.type
|
|
474
|
-
});
|
|
352
|
+
catch (error) {
|
|
353
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
354
|
+
result.errors.push(`Failed to configure sharding: ${errorMsg}`);
|
|
355
|
+
result.success = false;
|
|
475
356
|
}
|
|
476
357
|
}
|
|
477
358
|
return result;
|
|
478
359
|
}
|
|
479
|
-
async
|
|
360
|
+
async setupSharding(collection, sharding) {
|
|
480
361
|
const appId = this.config.appId;
|
|
481
362
|
if (!appId) {
|
|
363
|
+
throw new types_1.ValidationError('appId must be configured to setup sharding');
|
|
364
|
+
}
|
|
365
|
+
try {
|
|
366
|
+
await this.http.patch(`/api/apps/${appId}/collections/${collection}/sharding`, sharding);
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
370
|
+
new types_1.OnDBError('Failed to setup sharding', 'SHARDING_ERROR');
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
async deleteCollection(collection) {
|
|
374
|
+
const appId = this.config.appId;
|
|
375
|
+
if (!appId)
|
|
482
376
|
throw new types_1.ValidationError('appId must be configured');
|
|
377
|
+
try {
|
|
378
|
+
const response = await this.http.delete(`/api/apps/${appId}/collections/${collection}`);
|
|
379
|
+
return response.data;
|
|
380
|
+
}
|
|
381
|
+
catch (error) {
|
|
382
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
383
|
+
new types_1.OnDBError('Failed to delete collection', 'COLLECTION_ERROR');
|
|
483
384
|
}
|
|
385
|
+
}
|
|
386
|
+
async updateCollection(collection, updates) {
|
|
387
|
+
const appId = this.config.appId;
|
|
388
|
+
if (!appId)
|
|
389
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
484
390
|
try {
|
|
485
|
-
const response = await this.http.
|
|
391
|
+
const response = await this.http.patch(`/api/apps/${appId}/collections/${collection}`, updates);
|
|
486
392
|
return response.data;
|
|
487
393
|
}
|
|
488
394
|
catch (error) {
|
|
489
|
-
throw error instanceof types_1.
|
|
490
|
-
new types_1.
|
|
395
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
396
|
+
new types_1.OnDBError('Failed to update collection', 'COLLECTION_ERROR');
|
|
491
397
|
}
|
|
492
398
|
}
|
|
493
|
-
async
|
|
399
|
+
async getRetention(collection) {
|
|
400
|
+
const appId = this.config.appId;
|
|
401
|
+
if (!appId)
|
|
402
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
494
403
|
try {
|
|
495
|
-
const
|
|
496
|
-
const response = await this.http.post(`/api/apps/${appId}/relations`, request);
|
|
404
|
+
const response = await this.http.get(`/api/apps/${appId}/collections/${collection}/retention`);
|
|
497
405
|
return response.data;
|
|
498
406
|
}
|
|
499
407
|
catch (error) {
|
|
500
|
-
throw error instanceof types_1.
|
|
501
|
-
new types_1.
|
|
408
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
409
|
+
new types_1.OnDBError('Failed to get retention config', 'RETENTION_ERROR');
|
|
502
410
|
}
|
|
503
411
|
}
|
|
504
|
-
async
|
|
412
|
+
async setRetention(collection, request) {
|
|
413
|
+
const appId = this.config.appId;
|
|
414
|
+
if (!appId)
|
|
415
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
505
416
|
try {
|
|
506
|
-
const response = await this.http.
|
|
417
|
+
const response = await this.http.post(`/api/apps/${appId}/collections/${collection}/retention`, request);
|
|
507
418
|
return response.data;
|
|
508
419
|
}
|
|
509
420
|
catch (error) {
|
|
510
|
-
throw
|
|
421
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
422
|
+
new types_1.OnDBError('Failed to set retention config', 'RETENTION_ERROR');
|
|
511
423
|
}
|
|
512
424
|
}
|
|
513
|
-
async
|
|
425
|
+
async getRetentionCost() {
|
|
426
|
+
const appId = this.config.appId;
|
|
427
|
+
if (!appId)
|
|
428
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
514
429
|
try {
|
|
515
|
-
const response = await this.http.
|
|
430
|
+
const response = await this.http.get(`/api/apps/${appId}/retention/cost`);
|
|
516
431
|
return response.data;
|
|
517
432
|
}
|
|
518
433
|
catch (error) {
|
|
519
|
-
throw error instanceof types_1.
|
|
520
|
-
new types_1.
|
|
434
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
435
|
+
new types_1.OnDBError('Failed to get retention cost', 'RETENTION_ERROR');
|
|
521
436
|
}
|
|
522
437
|
}
|
|
523
|
-
async query
|
|
438
|
+
async sql(query, options) {
|
|
524
439
|
try {
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
return conditions.length === 1 ? conditions[0] : query_sdk_1.LogicalOperator.And(conditions);
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
if (request.limit) {
|
|
534
|
-
queryBuilder.limit(request.limit);
|
|
535
|
-
}
|
|
536
|
-
if (request.offset) {
|
|
537
|
-
queryBuilder.offset(request.offset);
|
|
538
|
-
}
|
|
539
|
-
return await queryBuilder.execute();
|
|
440
|
+
const body = { sql: query };
|
|
441
|
+
if (options?.includeHistory !== undefined)
|
|
442
|
+
body.include_history = options.includeHistory;
|
|
443
|
+
const response = await this.http.post('/query/sql', body);
|
|
444
|
+
return response.data;
|
|
540
445
|
}
|
|
541
446
|
catch (error) {
|
|
542
|
-
throw error instanceof types_1.
|
|
543
|
-
new types_1.
|
|
447
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
448
|
+
new types_1.OnDBError('SQL query failed', 'SQL_ERROR');
|
|
544
449
|
}
|
|
545
450
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
451
|
+
async sqlInsert(sql) {
|
|
452
|
+
try {
|
|
453
|
+
const body = { sql };
|
|
454
|
+
const response = await this.http.post('/insert/sql', body);
|
|
455
|
+
return response.data;
|
|
456
|
+
}
|
|
457
|
+
catch (error) {
|
|
458
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
459
|
+
new types_1.OnDBError('SQL insert failed', 'SQL_ERROR');
|
|
460
|
+
}
|
|
550
461
|
}
|
|
551
|
-
|
|
552
|
-
const
|
|
553
|
-
|
|
462
|
+
async listQueries() {
|
|
463
|
+
const appId = this.config.appId;
|
|
464
|
+
if (!appId)
|
|
465
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
466
|
+
try {
|
|
467
|
+
const response = await this.http.get(`/apps/${appId}/queries`);
|
|
468
|
+
return response.data.queries ?? response.data;
|
|
469
|
+
}
|
|
470
|
+
catch (error) {
|
|
471
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
472
|
+
new types_1.OnDBError('Failed to list predefined queries', 'QUERY_ERROR');
|
|
473
|
+
}
|
|
554
474
|
}
|
|
555
|
-
async
|
|
475
|
+
async createQuery(request) {
|
|
476
|
+
const appId = this.config.appId;
|
|
477
|
+
if (!appId)
|
|
478
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
556
479
|
try {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
queryBuilder = queryBuilder.whereField(field).equals(value);
|
|
560
|
-
}
|
|
561
|
-
return await queryBuilder.selectAll().executeUnique();
|
|
480
|
+
const response = await this.http.post(`/apps/${appId}/queries`, request);
|
|
481
|
+
return response.data;
|
|
562
482
|
}
|
|
563
483
|
catch (error) {
|
|
564
|
-
|
|
565
|
-
|
|
484
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
485
|
+
new types_1.OnDBError('Failed to create predefined query', 'QUERY_ERROR');
|
|
566
486
|
}
|
|
567
487
|
}
|
|
568
|
-
async
|
|
488
|
+
async getQuery(name) {
|
|
489
|
+
const appId = this.config.appId;
|
|
490
|
+
if (!appId)
|
|
491
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
569
492
|
try {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
queryBuilder = queryBuilder.whereField(field).equals(value);
|
|
573
|
-
}
|
|
574
|
-
if (options.limit) {
|
|
575
|
-
queryBuilder = queryBuilder.limit(options.limit);
|
|
576
|
-
}
|
|
577
|
-
if (options.offset) {
|
|
578
|
-
queryBuilder = queryBuilder.offset(options.offset);
|
|
579
|
-
}
|
|
580
|
-
const result = await queryBuilder.selectAll().execute();
|
|
581
|
-
if (!result.records) {
|
|
582
|
-
return [];
|
|
583
|
-
}
|
|
584
|
-
let records = result.records;
|
|
585
|
-
if (options.sort) {
|
|
586
|
-
records = records.sort((a, b) => {
|
|
587
|
-
const aVal = a[options.sort.field];
|
|
588
|
-
const bVal = b[options.sort.field];
|
|
589
|
-
if (options.sort.order === 'asc') {
|
|
590
|
-
return aVal > bVal ? 1 : -1;
|
|
591
|
-
}
|
|
592
|
-
else {
|
|
593
|
-
return aVal < bVal ? 1 : -1;
|
|
594
|
-
}
|
|
595
|
-
});
|
|
596
|
-
}
|
|
597
|
-
return records;
|
|
493
|
+
const response = await this.http.get(`/apps/${appId}/queries/${name}`);
|
|
494
|
+
return response.data;
|
|
598
495
|
}
|
|
599
496
|
catch (error) {
|
|
600
|
-
|
|
601
|
-
|
|
497
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
498
|
+
new types_1.OnDBError('Failed to get predefined query', 'QUERY_ERROR');
|
|
602
499
|
}
|
|
603
500
|
}
|
|
604
|
-
async
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
617
|
-
async updateDocument(collection, where, data, paymentCallback) {
|
|
618
|
-
const current = await this.findUnique(collection, where);
|
|
619
|
-
if (!current) {
|
|
620
|
-
return null;
|
|
621
|
-
}
|
|
622
|
-
const updated = {
|
|
623
|
-
...current,
|
|
624
|
-
...data,
|
|
625
|
-
updatedAt: new Date().toISOString(),
|
|
626
|
-
};
|
|
627
|
-
await this.store({
|
|
628
|
-
collection,
|
|
629
|
-
data: [updated],
|
|
630
|
-
}, paymentCallback);
|
|
631
|
-
return updated;
|
|
501
|
+
async deleteQuery(name) {
|
|
502
|
+
const appId = this.config.appId;
|
|
503
|
+
if (!appId)
|
|
504
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
505
|
+
try {
|
|
506
|
+
const response = await this.http.delete(`/apps/${appId}/queries/${name}`);
|
|
507
|
+
return response.data;
|
|
508
|
+
}
|
|
509
|
+
catch (error) {
|
|
510
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
511
|
+
new types_1.OnDBError('Failed to delete predefined query', 'QUERY_ERROR');
|
|
512
|
+
}
|
|
632
513
|
}
|
|
633
|
-
async
|
|
634
|
-
const
|
|
635
|
-
if (
|
|
636
|
-
|
|
514
|
+
async executeQuery(name, params, version) {
|
|
515
|
+
const appId = this.config.appId;
|
|
516
|
+
if (!appId)
|
|
517
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
518
|
+
try {
|
|
519
|
+
const queryParams = { ...params };
|
|
520
|
+
if (version !== undefined)
|
|
521
|
+
queryParams['v'] = version;
|
|
522
|
+
const response = await this.http.get(`/api/queries/${appId}/${name}/data`, { params: queryParams });
|
|
523
|
+
return response.data;
|
|
637
524
|
}
|
|
638
|
-
|
|
639
|
-
|
|
525
|
+
catch (error) {
|
|
526
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
527
|
+
new types_1.OnDBError('Failed to execute predefined query', 'QUERY_ERROR');
|
|
640
528
|
}
|
|
641
529
|
}
|
|
642
|
-
async
|
|
643
|
-
const
|
|
644
|
-
if (!
|
|
645
|
-
|
|
530
|
+
async getCollectionInfo(collectionId) {
|
|
531
|
+
const appId = this.config.appId;
|
|
532
|
+
if (!appId) {
|
|
533
|
+
throw new types_1.ValidationError('appId must be configured');
|
|
534
|
+
}
|
|
535
|
+
try {
|
|
536
|
+
const response = await this.http.get(`/api/apps/${appId}/collections/${collectionId}`);
|
|
537
|
+
return response.data;
|
|
538
|
+
}
|
|
539
|
+
catch (error) {
|
|
540
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
541
|
+
new types_1.OnDBError('Failed to get collection info', 'COLLECTION_ERROR');
|
|
646
542
|
}
|
|
647
|
-
const deleted = {
|
|
648
|
-
...existing,
|
|
649
|
-
deleted: true,
|
|
650
|
-
updatedAt: new Date().toISOString(),
|
|
651
|
-
};
|
|
652
|
-
await this.store({
|
|
653
|
-
collection,
|
|
654
|
-
data: [deleted],
|
|
655
|
-
}, paymentCallback);
|
|
656
|
-
return true;
|
|
657
543
|
}
|
|
658
|
-
async
|
|
544
|
+
async createRelation(request) {
|
|
659
545
|
try {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
}
|
|
664
|
-
return await queryBuilder.count();
|
|
546
|
+
const appId = this.config.appId || 'default';
|
|
547
|
+
const response = await this.http.post(`/api/apps/${appId}/relations`, request);
|
|
548
|
+
return response.data;
|
|
665
549
|
}
|
|
666
550
|
catch (error) {
|
|
667
|
-
|
|
668
|
-
|
|
551
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
552
|
+
new types_1.OnDBError('Failed to create relation', 'RELATION_ERROR');
|
|
669
553
|
}
|
|
670
554
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
555
|
+
async health() {
|
|
556
|
+
try {
|
|
557
|
+
const response = await this.http.get('/');
|
|
558
|
+
return response.data;
|
|
559
|
+
}
|
|
560
|
+
catch (error) {
|
|
561
|
+
throw new types_1.OnDBError('Health check failed', 'HEALTH_ERROR');
|
|
676
562
|
}
|
|
677
|
-
|
|
563
|
+
}
|
|
564
|
+
queryBuilder() {
|
|
565
|
+
const { AxiosHttpClient } = require('./query-sdk/adapters/HttpClientAdapter');
|
|
566
|
+
const httpClient = new AxiosHttpClient(this.http);
|
|
567
|
+
return new query_sdk_1.QueryBuilder(httpClient, this.config.endpoint, this.config.appId);
|
|
678
568
|
}
|
|
679
569
|
async getTaskStatus(ticketId) {
|
|
680
570
|
try {
|
|
@@ -682,8 +572,8 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
682
572
|
return response.data;
|
|
683
573
|
}
|
|
684
574
|
catch (error) {
|
|
685
|
-
throw error instanceof types_1.
|
|
686
|
-
new types_1.
|
|
575
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
576
|
+
new types_1.OnDBError('Failed to get task status', 'TASK_STATUS_ERROR');
|
|
687
577
|
}
|
|
688
578
|
}
|
|
689
579
|
async waitForTaskCompletion(ticketId, pollInterval = 2000, maxWaitTime = 600000) {
|
|
@@ -705,30 +595,30 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
705
595
|
if (typeof taskInfo.status === 'object' && 'Failed' in taskInfo.status) {
|
|
706
596
|
const error = taskInfo.status.Failed.error;
|
|
707
597
|
console.error(`🚫 Task ${ticketId} failed: ${error}`);
|
|
708
|
-
throw new types_1.
|
|
598
|
+
throw new types_1.OnDBError(`Task failed: ${error}`, 'TASK_FAILED');
|
|
709
599
|
}
|
|
710
600
|
if (typeof taskInfo.status === 'string' && taskInfo.status.toLowerCase().includes('error')) {
|
|
711
601
|
console.error(`🚫 Task ${ticketId} has error status: ${taskInfo.status}`);
|
|
712
|
-
throw new types_1.
|
|
602
|
+
throw new types_1.OnDBError(`Task error: ${taskInfo.status}`, 'TASK_FAILED');
|
|
713
603
|
}
|
|
714
604
|
await this.sleep(pollInterval);
|
|
715
605
|
}
|
|
716
606
|
catch (error) {
|
|
717
607
|
console.error(`❌ Error polling task ${ticketId}:`, error);
|
|
718
|
-
if (error instanceof types_1.
|
|
608
|
+
if (error instanceof types_1.OnDBError) {
|
|
719
609
|
if (error.code === 'TASK_FAILED' || error.statusCode === 404 || error.statusCode === 400) {
|
|
720
610
|
console.error(`🚫 Stopping polling due to permanent error: ${error.message}`);
|
|
721
611
|
throw error;
|
|
722
612
|
}
|
|
723
613
|
}
|
|
724
614
|
if (Date.now() - startTime >= maxWaitTime) {
|
|
725
|
-
throw new types_1.
|
|
615
|
+
throw new types_1.OnDBError(`Task completion timeout after ${maxWaitTime}ms. Last error: ${error instanceof Error ? error.message : String(error)}`, 'TASK_TIMEOUT');
|
|
726
616
|
}
|
|
727
617
|
console.warn(`⚠️ Temporary error polling task ${ticketId}, retrying in ${pollInterval}ms...`);
|
|
728
618
|
await this.sleep(pollInterval);
|
|
729
619
|
}
|
|
730
620
|
}
|
|
731
|
-
throw new types_1.
|
|
621
|
+
throw new types_1.OnDBError(`Task completion timeout after ${maxWaitTime}ms`, 'TASK_TIMEOUT');
|
|
732
622
|
}
|
|
733
623
|
async uploadBlob(request, paymentCallback) {
|
|
734
624
|
try {
|
|
@@ -742,13 +632,7 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
742
632
|
formData.append('metadata', JSON.stringify(request.metadata));
|
|
743
633
|
}
|
|
744
634
|
const uploadWithHeaders = async (headers = {}) => {
|
|
745
|
-
return await this.http.post(`/api/apps/${appId}/blobs/${request.collection}`, formData, {
|
|
746
|
-
headers: {
|
|
747
|
-
'Content-Type': 'multipart/form-data',
|
|
748
|
-
'X-App-Key': this.config.appKey,
|
|
749
|
-
...headers
|
|
750
|
-
}
|
|
751
|
-
});
|
|
635
|
+
return await this.http.post(`/api/apps/${appId}/blobs/${request.collection}`, formData, { headers: { 'Content-Type': 'multipart/form-data', ...headers } });
|
|
752
636
|
};
|
|
753
637
|
try {
|
|
754
638
|
const response = await uploadWithHeaders();
|
|
@@ -762,7 +646,7 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
762
646
|
const requirement = (0, x402_1.selectPaymentOption)(x402Response.accepts);
|
|
763
647
|
const quote = (0, x402_1.requirementToQuote)(requirement, x402Response.accepts);
|
|
764
648
|
if (!paymentCallback) {
|
|
765
|
-
throw new types_1.
|
|
649
|
+
throw new types_1.OnDBError('Payment required but no payment callback provided', 'PAYMENT_REQUIRED', 402, quote);
|
|
766
650
|
}
|
|
767
651
|
const payment = await paymentCallback(quote);
|
|
768
652
|
const x402Payload = (0, x402_1.buildPaymentPayload)(requirement, payment);
|
|
@@ -776,8 +660,8 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
776
660
|
}
|
|
777
661
|
}
|
|
778
662
|
catch (error) {
|
|
779
|
-
throw error instanceof types_1.
|
|
780
|
-
new types_1.
|
|
663
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
664
|
+
new types_1.OnDBError('Failed to upload blob', 'BLOB_UPLOAD_ERROR');
|
|
781
665
|
}
|
|
782
666
|
}
|
|
783
667
|
async retrieveBlob(request) {
|
|
@@ -786,12 +670,7 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
786
670
|
if (!appId) {
|
|
787
671
|
throw new types_1.ValidationError('appId must be configured to retrieve blobs');
|
|
788
672
|
}
|
|
789
|
-
const response = await this.http.get(`/api/apps/${appId}/blobs/${request.collection}/${request.blob_id}`, {
|
|
790
|
-
responseType: 'arraybuffer',
|
|
791
|
-
headers: {
|
|
792
|
-
'X-App-Key': this.config.appKey
|
|
793
|
-
}
|
|
794
|
-
});
|
|
673
|
+
const response = await this.http.get(`/api/apps/${appId}/blobs/${request.collection}/${request.blob_id}`, { responseType: 'arraybuffer' });
|
|
795
674
|
if (typeof global.window !== 'undefined' && typeof Blob !== 'undefined') {
|
|
796
675
|
const contentType = response.headers['content-type'] || 'application/octet-stream';
|
|
797
676
|
return new Blob([response.data], { type: contentType });
|
|
@@ -801,13 +680,10 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
801
680
|
}
|
|
802
681
|
}
|
|
803
682
|
catch (error) {
|
|
804
|
-
throw error instanceof types_1.
|
|
805
|
-
new types_1.
|
|
683
|
+
throw error instanceof types_1.OnDBError ? error :
|
|
684
|
+
new types_1.OnDBError('Failed to retrieve blob', 'BLOB_RETRIEVAL_ERROR');
|
|
806
685
|
}
|
|
807
686
|
}
|
|
808
|
-
async queryBlobMetadata(collection, where = {}) {
|
|
809
|
-
return await this.findMany(collection, where);
|
|
810
|
-
}
|
|
811
687
|
getDefaultIndexType(fieldType) {
|
|
812
688
|
switch (fieldType) {
|
|
813
689
|
case 'string':
|
|
@@ -822,6 +698,16 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
822
698
|
return 'string';
|
|
823
699
|
}
|
|
824
700
|
}
|
|
701
|
+
buildStoreResult(raw) {
|
|
702
|
+
return {
|
|
703
|
+
id: raw.id,
|
|
704
|
+
block_height: raw.celestia_height || 0,
|
|
705
|
+
transaction_hash: raw.blob_id || '',
|
|
706
|
+
celestia_height: raw.celestia_height || 0,
|
|
707
|
+
namespace: raw.namespace || '',
|
|
708
|
+
confirmed: raw.celestia_height > 0
|
|
709
|
+
};
|
|
710
|
+
}
|
|
825
711
|
validateStoreRequest(request) {
|
|
826
712
|
if (!request.root && !request.collection) {
|
|
827
713
|
throw new types_1.ValidationError('Either root or collection must be provided');
|
|
@@ -848,42 +734,21 @@ class OnChainDBClient extends eventemitter3_1.EventEmitter {
|
|
|
848
734
|
throw new types_1.ValidationError('Total data size exceeds 5MB limit');
|
|
849
735
|
}
|
|
850
736
|
}
|
|
851
|
-
handleHttpError(error) {
|
|
852
|
-
console.error(error);
|
|
853
|
-
if (error.response) {
|
|
854
|
-
const statusCode = error.response.status;
|
|
855
|
-
const message = error.response.data?.error || error.message;
|
|
856
|
-
if (statusCode >= 400 && statusCode < 500) {
|
|
857
|
-
return new types_1.ValidationError(message, error.response.data);
|
|
858
|
-
}
|
|
859
|
-
return new types_1.OnChainDBError(message, 'HTTP_ERROR', statusCode, error.response.data);
|
|
860
|
-
}
|
|
861
|
-
if (error.request) {
|
|
862
|
-
return new types_1.OnChainDBError('Network error - could not reach OnChainDB service', 'NETWORK_ERROR');
|
|
863
|
-
}
|
|
864
|
-
return new types_1.OnChainDBError(error.message, 'UNKNOWN_ERROR');
|
|
865
|
-
}
|
|
866
737
|
sleep(ms) {
|
|
867
738
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
868
739
|
}
|
|
869
|
-
buildRoot(collection) {
|
|
870
|
-
if (!this.config.appId) {
|
|
871
|
-
return collection;
|
|
872
|
-
}
|
|
873
|
-
return `${this.config.appId}::${collection}`;
|
|
874
|
-
}
|
|
875
740
|
resolveRoot(request) {
|
|
876
741
|
if (request.root) {
|
|
877
742
|
return request.root;
|
|
878
743
|
}
|
|
879
744
|
if (request.collection) {
|
|
880
|
-
return this.
|
|
745
|
+
return this.config.appId ? `${this.config.appId}::${request.collection}` : request.collection;
|
|
881
746
|
}
|
|
882
747
|
throw new types_1.ValidationError('Either root or collection must be provided');
|
|
883
748
|
}
|
|
884
749
|
}
|
|
885
|
-
exports.
|
|
886
|
-
|
|
750
|
+
exports.OnDBClient = OnDBClient;
|
|
751
|
+
OnDBClient.BASE_FIELDS = {
|
|
887
752
|
id: { type: 'string', index: true, unique: true },
|
|
888
753
|
createdAt: { type: 'date', index: true },
|
|
889
754
|
updatedAt: { type: 'date', index: true },
|